<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: duckie</title>
    <description>The latest articles on DEV Community by duckie (@duckiec).</description>
    <link>https://dev.to/duckiec</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4164226%2F475d5412-7814-4f25-a25b-cd256dfd29e7.png</url>
      <title>DEV Community: duckie</title>
      <link>https://dev.to/duckiec</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/duckiec"/>
    <language>en</language>
    <item>
      <title>Stop giving AI cluster-admin. Here is a read-only, POSIX-jailed K8s incident responder.</title>
      <dc:creator>duckie</dc:creator>
      <pubDate>Tue, 06 Oct 2026 13:40:35 +0000</pubDate>
      <link>https://dev.to/duckiec/why-i-built-srek3s-an-ai-incident-responder-that-cannot-write-to-your-cluster-1b29</link>
      <guid>https://dev.to/duckiec/why-i-built-srek3s-an-ai-incident-responder-that-cannot-write-to-your-cluster-1b29</guid>
      <description>&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/duckiec" rel="noopener noreferrer"&gt;
        duckiec
      &lt;/a&gt; / &lt;a href="https://github.com/duckiec/SREK3S" rel="noopener noreferrer"&gt;
        SREK3S
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A fail-closed, AI-powered Site Reliability Engineer for your Kubernetes cluster.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/duckiec/SREK3S/docs/assets/banner.svg"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fduckiec%2FSREK3S%2FHEAD%2Fdocs%2Fassets%2Fbanner.svg" alt="SREK3S banner: the project mark and wordmark" width="100%"&gt;&lt;/a&gt;
  &lt;br&gt;
  &lt;p&gt;
    &lt;a href="https://github.com/duckiec/SREK3S/actions/workflows/ci.yaml" rel="noopener noreferrer"&gt;&lt;img src="https://github.com/duckiec/SREK3S/actions/workflows/ci.yaml/badge.svg?branch=main" alt="CI"&gt;&lt;/a&gt; &lt;a href="https://github.com/duckiec/SREK3S/actions/workflows/release.yaml" rel="noopener noreferrer"&gt;&lt;img src="https://github.com/duckiec/SREK3S/actions/workflows/release.yaml/badge.svg" alt="Release"&gt;&lt;/a&gt; &lt;a href="https://github.com/duckiec/SREK3S" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/1a742947efd390f6b111809fccc7c62dd045497ceb1e5d3261ce42caf8b39287/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f706c6174666f726d2d6c696e7578253246616d6436342532302537432532306c696e757825324661726d36342d343635356462" alt="Multi-arch"&gt;&lt;/a&gt; &lt;a href="https://go.dev" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/6b4ff39b898a48e8b1c1c987f5e5c19e1b4ec96af210ecafa1179b2720162c60/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f676f2d312e32352532422d3030414444383f6c6f676f3d676f" alt="Go"&gt;&lt;/a&gt; &lt;a href="https://www.python.org" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/d68066cf28119dd5262b561bd41db741c69a9e2daf49c3c661770aea5a409b35/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f707974686f6e2d332e31312d3337373641423f6c6f676f3d707974686f6e" alt="Python"&gt;&lt;/a&gt; &lt;a href="https://github.com/duckiec/SREK3S/LICENSE" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/7013272bd27ece47364536a221edb554cd69683b68a46fc0ee96881174c4214c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d626c75652e737667" alt="License: MIT"&gt;&lt;/a&gt; &lt;a href="https://github.com/duckiec/SREK3S/actions/workflows/ci.yaml" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/1a7c01848dbebf01789df8a0010be73fe1b8305bcde962241511a56f717aac95/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f74657374732d31303837253230706173736564253230253743253230313739253230676f2d73756363657373" alt="Tests"&gt;&lt;/a&gt;
  &lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Most Kubernetes AI agents are a rootkit waiting to happen. They demand cluster-admin rights and stream raw stdout to external LLM APIs. SREK3S is a zero-trust, read-only incident response agent. It intercepts pod crashes, scrubs secrets in-memory before network egress, and sandboxes LLM triage in a POSIX-jailed worker. It generates verified GitOps patches with strictly zero cluster write authority and deterministically fails closed to human review.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Features&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Zero cluster mutations&lt;/strong&gt;: namespaced &lt;code&gt;get&lt;/code&gt;/&lt;code&gt;list&lt;/code&gt;/&lt;code&gt;watch&lt;/code&gt; only. No ClusterRole, no write field on either wire contract, no mounted token on the Agent.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;In-memory secret scrubbing&lt;/strong&gt;: 11 ordered regex rules run before egress. Nothing unmasked reaches a queue, a disk, or a socket.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AST YAML validation&lt;/strong&gt;: a patch survives a YAML AST parse, then &lt;code&gt;git apply --check&lt;/code&gt; against the target's own bytes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deterministic Tier-2 escalation&lt;/strong&gt;: tier, patch, and every flag are computed before a model is consulted…&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/duckiec/SREK3S" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Most "AI SRE agents" are catastrophic control failures dressed as features. By binding service accounts to &lt;code&gt;cluster-admin&lt;/code&gt; and mounting raw credentials, they turn container &lt;code&gt;stdout&lt;/code&gt;—which routinely leaks AWS keys and Postgres passwords—into an exfiltration pipeline to third-party LLMs. Worse, granting the model write authority turns a log-line prompt injection into a full cluster mutation requiring zero vulnerabilities in the model itself.&lt;/p&gt;

&lt;p&gt;I built SREK3S to take the opposite approach: remove the capability entirely. SREK3S is a zero-trust, read-only AI incident responder. Because it holds no cluster write authority anywhere in its architecture, the question of whether the model &lt;em&gt;would&lt;/em&gt; do something dangerous never arises—it physically can't.&lt;/p&gt;

&lt;h2&gt;
  
  
  What SREK3S Fixes
&lt;/h2&gt;

&lt;p&gt;Instead of relying on prompt hardening, SREK3S enforces strict, structural security boundaries:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;In-Memory Redaction:&lt;/strong&gt; No secret crosses the network egress boundary. The Go Sentinel uses a hermetic package to scrub secrets in-memory, on the node, before any socket is opened.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Ordered, Normative Rules:&lt;/strong&gt; Redaction follows 11 strict rules (targeting PEM blocks, JWTs, AWS keys), executing the cross-line pass first to prevent partial unmasking.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Zero-Write RBAC:&lt;/strong&gt; The Sentinel is bound to a namespaced &lt;code&gt;Role&lt;/code&gt; limited strictly to &lt;code&gt;get&lt;/code&gt;, &lt;code&gt;list&lt;/code&gt;, and &lt;code&gt;watch&lt;/code&gt;. There is no &lt;code&gt;ClusterRole&lt;/code&gt; or binding.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Credential-Free Agent:&lt;/strong&gt; The Python Agent runs with &lt;code&gt;automountServiceAccountToken: false&lt;/code&gt; as UID 10001 with a read-only root filesystem and all capabilities dropped.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fs4etbffvqucwzyq1yx3u.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fs4etbffvqucwzyq1yx3u.gif" alt="Live execution: The Sentinel intercepts an AWS Secret Access Key in a crashing pod and scrubs it in-memory before it ever hits the network." width="760" height="451"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Live execution: The Sentinel intercepts an AWS Secret Access Key in a crashing pod and scrubs it in-memory before it ever hits the network.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Rigorous Engineering (Not Just Another Vibecoded Wrapper)
&lt;/h2&gt;

&lt;p&gt;Instead of blindly piping model hallucinations to &lt;code&gt;kubectl apply&lt;/code&gt;, SREK3S treats LLM output with extreme suspicion.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;YAML AST Validation:&lt;/strong&gt; The &lt;code&gt;verify_yaml_ast&lt;/code&gt; function parses original and patched documents into Abstract Syntax Trees to prove exactly one semantic field changed, catching type errors simple diffs miss.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;True GitOps Failsafes:&lt;/strong&gt; It runs &lt;code&gt;git apply --check&lt;/code&gt; in a materialized throwaway repo against the exact bytes provided, refusing to normalize or repair malformed output.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Disposable POSIX Sandboxing:&lt;/strong&gt; Analysis executes in a child process bound by strict limits (256 MiB memory, 1 CPU-second, 0 core dumps). No state survives the investigation.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Fail-Closed Law:&lt;/strong&gt; Incident routing is deterministic. If evidence is ambiguous (e.g., a generic &lt;code&gt;CrashLoopBackOff&lt;/code&gt;), SREK3S refuses to guess, defaulting to a Tier-2 architectural review that dispatches a Markdown war room report without proposing a patch.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  I Threw Everything At It: The Verification Gauntlet
&lt;/h3&gt;

&lt;p&gt;I didn't just write happy-path tests; I tried to break this system in every way imaginable. The codebase passes every gate I could throw at it (&lt;code&gt;go vet&lt;/code&gt;, &lt;code&gt;gofmt&lt;/code&gt;, &lt;code&gt;-race&lt;/code&gt;, &lt;code&gt;black&lt;/code&gt;, &lt;code&gt;flake8&lt;/code&gt;, &lt;code&gt;mypy&lt;/code&gt;, &lt;code&gt;pytest&lt;/code&gt;), currently sitting at 1087 passing tests (179 in Go). &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;The Scrubber Corpus:&lt;/strong&gt; The memory scrubber is validated against a 46-case corpus spanning 8 groups. This includes 32 maskable secrets and a dedicated &lt;code&gt;negative_controls&lt;/code&gt; group of 6 cases that &lt;em&gt;must&lt;/em&gt; survive untouched—because a redaction tool that just blanks out everything is completely useless. &lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Performance Bounding:&lt;/strong&gt; The system enforces a throughput budget of ≥20,000 lines/sec/core. This ensures the masking stays well inside the 2-second detection budget, with rules compiled exactly once and never recompiled in the hot path.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Prose-to-Code Assertions:&lt;/strong&gt; I built a build gate (&lt;code&gt;test_scrubber_manifest_spec.py&lt;/code&gt;) that parses the normative rule table straight out of &lt;code&gt;CONTRIBUTING.md&lt;/code&gt; and fails the build if the code's rule IDs, order, or patterns drift from the documentation.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;RBAC Enforcement:&lt;/strong&gt; &lt;code&gt;TestSentinelRoleGrantsNoMutatingVerb&lt;/code&gt; parses the deployment YAML and fails the build if any verb other than &lt;code&gt;get&lt;/code&gt;, &lt;code&gt;list&lt;/code&gt;, or &lt;code&gt;watch&lt;/code&gt; ever sneaks into the Sentinel's Role.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Catching Real Defects:&lt;/strong&gt; I document my failures in &lt;code&gt;lessons-learned.md&lt;/code&gt;. Exhaustive testing caught edge cases like a &lt;code&gt;CrashLoop&lt;/code&gt; fixture rendered undetectable by &lt;code&gt;restartPolicy: Never&lt;/code&gt;, a Service selector that routed nowhere despite 16 green manifest tests, and a &lt;code&gt;terminationGracePeriodSeconds&lt;/code&gt; block mistakenly placed at the container level—which text-matching tests missed, but the actual API server rejected. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;SREK3S extracts the genuinely useful capabilities of LLMs—reading crash evidence and forming hypotheses—without handing over the keys to the cluster.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it in 60 Seconds
&lt;/h2&gt;

&lt;p&gt;SREK3S is open-source and MIT-licensed. Because it relies on standard client-go informers, it deploys cleanly to any conformant cluster (k8s, k3s, Minikube, EKS).&lt;/p&gt;

&lt;p&gt;You do not need to build Go binaries or compile Python to test it. We publish multi-arch images directly to GHCR.&lt;/p&gt;

&lt;p&gt;Clone the repo, apply the quickstart overlay, and detonate the provided memory-leak fixture to watch the in-memory redaction happen live:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/duckiec/SREK3S" rel="noopener noreferrer"&gt;View the repository and Quick Start on GitHub →&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>kubernetes</category>
      <category>security</category>
      <category>go</category>
    </item>
  </channel>
</rss>
