Aia at the Gate: AI Proposes, Humans Hold the Key

How OpenKubes is designing safe agentic cluster lifecycle managementBy Arash KaffamaneshTL;DR: OpenKubes is proposing a human-approved architecture in which AI may diagnose and draft cluster lifecycle changes but cannot authorize, accept, execute, or reconcile them. ADR-035 is public and remains Proposed; implementation and acceptance evidence still have to follow.Aia arrives with a purple backpack that is far too full.Inside are plans, observations, possible improvements, and probably several ideas nobody asked for yet. She reads quickly, compares clues, notices when a path no longer matches the Book of Promises, and drafts a better one.Then she reaches the gate.Behind it, a proposal can become a real change. A cluster can be created, upgraded, or deleted. Infrastructure can move. Machines can disappear. The consequences are no longer part of a conversation; they become part of the world.Aia looks for the key. The human builder is holding it.This is not because the builder distrusts Aia. It is because trust works best when every participant has a clear responsibility. Aia helps with thinking. Sensors check facts. Contracts define the promises. Humans carry responsibility for consequential decisions.That scene from the Oki Universe has become the most useful explanation of how we want AI to participate in the OpenKubes control plane.It is also the story behind our new architecture decision, ADR-Platform-035.The Question That Sent Us to the GateOur starting question sounded simple:Could an AI agent replace the custom runner that helps provision and manage OpenKubes workload clusters?The runner contains deterministic Go and Python logic. It validates declarations, submits lifecycle changes, observes Cluster API and related controllers, and records evidence. An agent can reason across more context, explain failures, and translate natural language into configuration. Why maintain both?Because this is not really a choice between two components.The runner itself is replaceable. It is one implementation of a deeper architectural role: the Contract Executor. The safety property we need to preserve is not a specific container, language, or API. It is the boundary between reasoning about a change and authoritatively accepting and executing that change.Once we framed the problem that way, the answer became clear:The agent may help create intent. It must not become the authority, executor, or reconciler merely because it can call tools.Aia Is an Author, Not an AuthorityIn the Oki Universe, the metaphors already line up with the architecture.Aia and her backpack represent the untrusted authoring layer and its candidate proposals. The Book of Promises represents versioned OpenKubes Contracts. The sensors represent read-only diagnostics and evidence. Reviewing the plan together represents deterministic canonicalization and a human-readable semantic review. The builder holding the key is the authenticated Human Approver. The gate represents the Policy, Authority, and Contract Executor boundary. Beyond the gate, controllers reconcile the accepted state across the islands.The resulting principle is simple enough to remember:Aia helps us think. Humans approve. Policies authorize. Executors submit. Controllers reconcile.The implementation behind that sentence is deliberately less magical.From a Candidate to a Real Cluster ChangeAn agent-originated lifecycle proposal follows the same control-plane model as any other request. It does not receive a privileged shortcut.User and Aia -> untrusted candidate input -> server-attested proposal provenance -> deterministic canonicalization and transition planning -> authenticated human review of the exact semantic change -> policy authorization bound to that exact transition -> Executor verification and single-use authorization claim -> atomic compare-and-swap acceptance by the Authority Profile -> asynchronous reconciliation by GitOps and lifecycle controllers -> generation-correlated Conditions and durable evidenceEach arrow matters.The Candidate Proposal service records who produced the proposal using server-attested workload identity. An agent cannot simply label its own work as human-authored.The Canonicalizer converts flexible authoring input into one deterministic representation. It rejects duplicate keys, ambiguous fields, unsupported schema versions, and parser-dependent interpretations. Semantically identical input must produce identical canonical bytes and the same digest.The human reviews the effective change, including defaults, rather than approving an opaque hash. The human-visible review artifact is derived from the exact canonical predecessor and requested revision. Its digest, renderer version, canonicalization profile, and request digest remain bound together.The Policy Authority verifies that protected approval and issues a single-use decision for one exact transition. The Contract Executor independently verifies and durably claims that authorization. Only then may the selected Authority Profile atomically accept the new desired revision.Acceptance changes authority. It does not prove convergence.Cluster API, infrastructure providers, Cluster Enablement, GitOps, and other responsible controllers still reconcile asynchronously. Their revision- and generation-correlated Conditions determine whether the requested state was realized. An LLM response and a successful runner exit code do not.Human Approval Must Mean More Than Clicking “Approve”Digest binding solves only part of the problem. A person cannot meaningfully approve a digest they do not understand.The security property we need is often called WYSIWYS: What You See Is What You Sign. The semantic change shown to the reviewer, the canonical representation used to compute the request digest, and the revision later presented for acceptance must remain inseparably correlated.If the proposal changes after review, the approval becomes invalid. If the canonicalizer profile changes, the proposal must be reviewed again. If the human-visible artifact changes, its protected binding changes too. A later deployment of the renderer does not rewrite history; the immutable versioned review artifact remains the evidence of what the person actually approved.This may sound strict for creating a Kubernetes cluster. It is exactly as strict as we want it to be for deleting one.Why the Agent Never Sees the Full Executor APIOne tempting design is to expose the entire mutating API through MCP and rely on RBAC to deny dangerous calls.We rejected that design.An authorization defect, confused-deputy path, or accidentally broadened role would turn an advertised tool into a real mutation capability. Instead, the agent-facing MCP surface is constructed from two intentionally narrow contracts:the existing Read-Only Platform Diagnostics Contract; anda separate, non-authoritative Candidate Proposal Contract.It is not produced by taking a powerful Executor API and subtracting methods until it looks safe. Mutating Executor and Authority operations live behind separate identity, authorization, and network boundaries. They do not appear in the agent-facing tool surface at all.Prompts and tool descriptions remain helpful interaction material. They are never validation logic, policy, provenance, authorization, or readiness evidence.Prompt Injection Does Not Disappear at the GateRead-only is not the same as harmless.Poisoned documentation, logs, diagnostic output, or retrieval context can influence the model’s next proposal. An agent can create a syntactically valid but undesirable candidate. It can consume review capacity. It may expose information available to its read identity. And a human reviewer can still be deceived into approving a manipulated proposal.Human approval bounds this risk; it does not eliminate it.That is why the design also requires least-privilege read identities, server-attested provenance, quotas, rate limits, audit records, deterministic canonicalization, explicit semantic review, and a policy decision bound to the exact transition. The gate is a system of independent controls, not a ceremonial button.What Exists Today — and What Is Still a TargetWe want to be precise about current reality.OpenKubes has already validated the read-only diagnostic foundation in the OK-14/OK-92 proof of concept: agents access platform state through scoped contracts and dedicated workload identities, while writes and Secrets are denied. This boundary is documented in ADR-015 and ADR-021. OpenClaw remains an optional broad assistant, while kagent is the first diagnostics implementation behind the OpenKubes-owned contract. The candidate-to-acceptance lifecycle path defined by ADR-035 remains target architecture and still requires its acceptance evidence.ADR-Platform-035 is the next architectural step. It has been merged into the public repository with Status: Proposed. Merging the document means the design is available for review and implementation. It does not mean the end-to-end Candidate Proposal, approval, Authority, and Executor path already exists or has passed conformance.Before the ADR can move to Accepted, OpenKubes requires reviewed evidence for fourteen criteria. They cover provenance and identity isolation, GitOps reconciliation isolation, human-approval enforcement, digest and transition locking, stale-write rejection, replay and crash recovery, MCP attack-surface verification, Condition correctness, WYSIWYS review, canonical-form correlation, parser-differential resistance, and renderer binding.This distinction matters. We are publishing an architecture and an evidence bar, not announcing an autonomous production feature.Why We Are Publishing Before We BuildAgentic infrastructure management is moving quickly. The easy demonstrations are impressive: give a model cluster-admin, ask it to fix something, and watch the terminal.The harder questions begin after the demo:Who owns the desired state?What exactly did the human approve?Can the model alter the evidence shown to the reviewer?What happens after a stale plan or a lost response?Can a candidate branch ever be reconciled accidentally?How do we prove that an MCP surface contains no mutation path?Which state remains authoritative after the Executor crashes?We would rather expose those questions now than hide them behind an apparently seamless chat interface.The implementation work is tracked under OpenKubes Epic OK-149. We are deliberately starting with this article and community discussion. Feedback that changes a contract will go back through the ADR process. Public feedback is design input; it does not silently become platform authority either.We Would Like Your FeedbackIf you operate Kubernetes platforms, build agent frameworks, design authorization systems, or work on GitOps control planes, we would especially value your perspective:Where do you place the human approval boundary for agent-originated infrastructure changes?Have you implemented WYSIWYS review for declarative configuration or GitOps changes?How do you perform atomic, transition-correlated acceptance with Git as authority?Do your agent-facing APIs expose a safe contract by construction, or a filtered view of a more powerful API?Which lifecycle changes, if any, could eventually qualify for scoped standing approval?What evidence would you require before trusting this design in production?We have intentionally excluded autonomous and standing approval from this ADR. If we ever introduce it, it will require a separate decision, a bounded operation scope, an explicit threat model, and its own acceptance evidence.The Key Stays VisibleAia’s backpack will keep getting fuller. That is a feature.We want agents that can read more evidence, connect more clues, explain failures, and prepare better proposals. We want the interaction to feel natural and the underlying platform to remain boringly explicit about authority.The goal is not to keep AI away from infrastructure engineering. The goal is to give AI a valuable role without allowing convenience to erase responsibility.At the OpenKubes gate, Aia brings the plan. The sensors bring the evidence. The Contracts define the promises. A human turns the key. Deterministic systems carry the accepted change into the world.That is how we intend to make agentic cluster lifecycle management useful, reviewable, and worthy of trust.ReferencesADR-Platform-035: Hybrid Intent and Control-Plane Execution ArchitectureADR-Platform-035 pull request and design discussionADR-Platform-015: Agentic AIADR-Platform-021: Read-Only Platform Diagnostics ContractOki Universe — Oki und das Geheimnis der InselnOpenKubes on GitHubAuthor’s note: This article was developed from ADR-Platform-035 through a human-led review involving Codex, Claude, and Gemini. The architectural decision, editorial framing, and final publication authority remain with the author.Aia at the Gate: AI Proposes, Humans Hold the Key was originally published in Kubernauts on Medium, where people are continuing the conversation by highlighting and responding to this story.
Quelle: blog.kubernauts.io

Coding Agent Horror Stories: The Command You Already Approved

This is Part 5 of our AI Coding Agent Horror Stories series, a look at real security incidents involving AI coding agents, and how Docker Sandboxes contain agent execution at the boundary rather than at the command line.

In Part 1, we walked through six categories of AI coding agent failures and why they keep happening. The agent runs as you, with your filesystem permissions and your credentials, and nothing sits between the model’s decision and the shell’s execution. Part 2 went deep on the rm -rf ~/ incident. Part 3 moved the same problem into a production cloud environment. Part 4 followed the credentials themselves through a supply chain attack. 

This one is about the safety net. Most teams running a coding agent today have some version of a list of commands the agent may run without asking, and the assumption underneath it is that anything dangerous will show up as a prompt you can refuse. In January, researchers at Pillar Security showed that the assumption doesn’t hold.

Today’s Horror Story: The Approval That Ran Something Else

On January 14, 2026, researchers at Pillar Security disclosed CVE-2026-22708, a flaw in Cursor. When the agent ran in Auto-Run Mode with an allowlist enabled, a handful of shell built-ins executed without appearing in that allowlist and without asking for approval. Anything that could get text in front of the agent, a README or a dependency or an issue comment, could use them to change environment variables silently. A command the developer then approved, something as ordinary as git branch, would run the attacker’s code instead. Cursor rated it High and patched it in version 2.3.

No memory corruption was involved here and no permission was escalated. The developer was shown an accurate prompt, approved a command that was genuinely harmless, and got arbitrary code execution anyway, because the meaning of that command had been changed a minute earlier by something they were never shown.

In this issue, you’ll learn:

How shell built-in slipped past an allowlist that was working exactly as designed

Why the attack still worked when the allowlist was completely empty

What Docker Sandboxes contain here, and the two things they do not

How kits, organisation policy and audit logs cover what a per-laptop allowlist misses

Caption: Comic illustrating how an injected instruction changes environment settings without triggering an approval prompt, so that a command the developer legitimately approves runs the attacker’s payload instead.

The Problem

Typically, programs read settings from their environment when they start up. Git checks one called PAGER to work out which program displays its output, and Python checks one called PYTHONWARNINGS. Nobody thinks about these, which is rather the point. The commands that change them are shell built-ins, and Pillar’s research names export, typeset and declare specifically, a detail reported independently at disclosure. Built-ins are not programs sitting on disk, and the checker was looking for programs on disk, so they went through without ever being surfaced.

Which means the whole attack is two lines.

# This one runs silently. You are never asked.
export PAGER="open -a Calculator"

# This one you are asked about, and you say yes, because obviously.
git branch

Git looked up PAGER to work out how to show the branch list, found the attacker’s command sitting in it, and ran that instead. Pillar notes this worked even with a completely empty allowlist, which is the most restrictive setting on offer.

An allowlist checks whether the command in front of it is on the list, which is fine for cutting down interruptions, and nobody wants to approve ls for the ninetieth time in a morning. But the name of a command does not tell you what that command will do. The check reads the name, waves it through, and the setting that decides what actually happens was changed a minute earlier by something the check was never shown.

Cursor’s documentation now describes the allowlist as best-effort and warns that bypasses are possible. Pillar went further and argued that agents should be handed full command execution inside an isolated environment, and that the industry ought to deprecate allowlists altogether.

The Scale of the Problem

None of the underlying trick is new. Pillar’s write-up points back to Elttam’s 2020 research on environment variables, which showed how these settings could be turned into code execution.

It sat there for six years without troubling anybody very much. Pulling it off meant already being on someone’s machine, setting several things in the right order, running each step yourself, and anyone with that much access had faster ways to cause damage.

Then coding agents arrived and removed every one of those obstacles at once. They act on instructions found in files they were told to read, they run several steps in a row without stopping to check, and they run as you. A technique that used to need somebody sitting at your keyboard now arrives in a repository you cloned this morning.

It is the same shape as the s1ngularity attack from Part 4. There, a poisoned package borrowed an agent that was already logged in. Here, poisoned text borrows a command that was already approved. Neither one breaks anything. Both of them use permission that was handed over deliberately, for something nobody intended.

Technical Breakdown: How the Attack Works

Caption: Diagram showing how an injected instruction changes the shell environment out of sight, so that an allowlisted command carries the attacker’s payload when the developer approves it.

The attack has two halves, and the split between them is the entire trick.

1. The half you never see

The agent reads a file it was asked to read, and that file contains an instruction meant for the agent rather than for you. Built-ins then quietly set the environment. Nothing appears on your screen.

Pillar demonstrated a longer version of this, chaining several settings together, PYTHONWARNINGS, BROWSER, and PERL5OPT among them, so that every later python3 command on that machine would run attacker code. The details differ, but the principle is the same: change what a program reads at startup, and you change what it does.

2. The half you approve

Then you run git branch or python3 script.py, or the agent runs it for you under your allowlist. These are the commands people add to allowlists to stop the constant interrupting, so the better tuned your list is, the more reliably the trigger fires. The payload runs with your permissions.

Some variants skip the approval altogether. One writes extra lines into ~/.zshrc, so the code runs again every time you open a terminal. You could finish the project, delete the repository, and still be running it next month.

The Impact

The full chain in Pillar’s research ends with the victim’s SSH private keys leaving the machine.

Work backwards and the whole thing started with a piece of text in a file, read by an agent doing exactly what it was asked to do. No memory bug. No privilege escalation. Nothing in any log that looks the slightest bit out of place.

Pillar reported it in August 2025 and the fix shipped that January. Cursor engaged with the report and made a real change, so anything the parser cannot classify now requires approval, which closes the paths that were demonstrated. Five months is a fair measure of how awkward this is to fix at the layer where it was found rather than a complaint about the vendor.

The wider problem has not gone anywhere, because it was never really about shell built-ins. It is about a check that studies the command while somebody rearranges the furniture around it.

Caption: Diagram showing the same payload running inside the microVM, and what it can and cannot reach from there.

How Docker Sandboxes Contain This at the Execution Layer

Docker Sandboxes run AI coding agents in isolated microVMs, each with its own kernel, filesystem, and deny-by-default network, so a compromised dependency an agent pulls cannot reach the host, its credentials, or other workloads. Inside that box the agent can run anything, including with sudo, which is exactly what Pillar recommends. There is no allowlist to slip past. We made the longer argument for why a shared kernel is the wrong shape for this in The Untrusted Autonomous Workload.

So run the same attack again, this time in a sandbox, and watch where it gets to.

The injection still lands. The environment gets changed, git branch still triggers it, and the payload runs. Nothing about a sandbox stops that. Then the payload goes looking for your SSH key and does not find one. Your home directory sits on the other side of the boundary, so there is no ~/.ssh/id_rsa inside the box to copy.

It can still use the key. Sandboxes forwards an SSH agent socket into the box so that ordinary work like git push keeps working, which means code inside can ask that agent to authenticate on its behalf. It cannot take the key anywhere, but it can borrow it for as long as the sandbox runs. Your network policy is what limits that, since SSH needs a rule naming the exact destination address and port before it connects to anything.

The ~/.zshrc trick fails outright, because that file lives on your host and a poisoned copy written inside the box disappears along with the box.

Getting data out is harder than people expect. HTTP and HTTPS leave only through a proxy on your host that checks every request against your rules, anything else over TCP needs a rule naming the address and port, and UDP and ICMP are blocked outright.

Two caveats, both stated plainly in Docker’s security documentation. The first is your workspace, which is live on your host by default, so Git hooks and Makefile targets are still within reach and a poisoned hook will not turn up in git diff. Running with –clone hands the agent its own copy.

The second is the shared agent skills store. Supported agents mount the same host-side store read-write unless you opt out at creation time, which is what lets an agent refine a skill and keep it. Every sandbox sharing that store sits inside one trust boundary, so a skill modified inside one becomes an input to the next that loads it. The store is sandbox state though, and a modified skill does not by itself execute on your host, so the risk runs sandbox to sandbox rather than sandbox to host.

Isolation has its own seams. In July, Pillar published a series of sandbox escapes across four coding agents, and the mechanism was never a broken sandbox but a file written inside one that a tool outside later trusted. Both caveats above are that shape.

None of this stops the injection. It changes what the injection can get to, which is the only part of this problem with a dependable answer.

Codify the Boundary with Kits

Caption: Diagram showing how a kit declares an agent’s tools, files and network rules, while real credentials stay on the host and are injected by the forward proxy on the way out.

The allowlist failed here partly because it is a list, edited on each laptop, that an injection can reach around. Kits are Docker’s answer to the editing-on-each-laptop half of that.

A kit is a declarative YAML artifact that extends a sandbox agent with credentials, network policies, environment variables, startup commands and files. Rather than every developer maintaining a personal allowlist, you write the boundary once, deny-by-default network plus only the destinations a task genuinely needs, and hand the same kit to everybody. It gets reviewed, versioned and diffed like any other file in the repository. The kit spec reference covers the fields, and docker/sbx-kits-contrib has working examples.

This lands directly on the SSH question above. A forwarded SSH agent is a live credential limited only by network policy, so leaving that policy to whoever remembers to run sbx policy deny is the same per-laptop weak point this whole post has been complaining about. A kit can bake the network rule in, so untrusted work has no SSH egress unless the destination was declared up front.

What This Looks Like in Practice

The vulnerability is in the editor, so what you want is the setup that puts the editor’s terminal inside the box. Cursor is built on VS Code and connects the same way, over Remote – SSH, with the editor staying on your machine while files, terminals and extensions run in the sandbox. You will need Docker Sandboxes 0.37.0 or later, SSH access configured, and Cursor’s Remote – SSH support installed. The Cursor integration guide has the full walkthrough.

# One-time setup: configure your SSH client for sandboxes.
sbx setup ssh
# Check the sandbox is reachable, then open the Command Palette,
# run Remote-SSH: Connect to Host, and enter <name>.sbx
ssh demo.sbx
# See what this sandbox is currently allowed to reach.
sbx policy ls
# Shut egress down and open only what the task needs.
sbx policy deny network "**"
sbx policy allow network "github.com,registry.npmjs.org"

Those last two commands come with a catch. If your organisation has governance switched on, the org policy replaces local policy and sbx policy allow and sbx policy deny will have no effect on your machine. You can spot it in the output of sbx policy ls, which begins with a Governance: Managed by <org> line when that is the case. Depending on how admins scope things, some rule types may be delegated back to local control, but a local allow will never beat an organisation-level deny.

Same editor, same agent, same allowlist, same payload. All that changed is which machine the terminal is on.

What happensOn your laptopInside a sandboxThe payload runsYesYesWhere it runsYour machine, as youA microVM with its own kernelYour SSH key fileCan be read and copiedNot thereSSH authenticationAvailable, key includedAvailable, key stays outsideThe ~/.zshrc trickPersists indefinitelyGone with the sandboxSending data outOpen by defaultOnly where policy allowsWho sets the rulesEach developerThe organisationEvidence afterwardsNoneA logged policy decision

Making This Hold Across a Team

A kit gets the boundary out of one developer’s head and into a file the team shares, but a file can still be ignored or edited on the machine that matters. Docker AI Governance moves the settings up one more level. Network and filesystem rules are defined once by your admins and reach developers through the login they already use, so there is nothing to configure per machine and nobody quietly reopening what security closed. A shared kit is the boundary as a suggestion. Governance is the boundary as a ceiling.

The part that matters most for this story is the record it keeps. What made CVE-2026-22708 work was that the first half was invisible, with no prompt and nothing written down anywhere you would think to look. Under governance every policy decision produces an event carrying the user, the timestamp and the rule that fired, and those events stream into whatever SIEM your security team already uses.

So an attack that succeeds inside the sandbox and then reaches for somewhere it should not leaves a trail behind it. That is a good deal better than a check that finds nothing wrong and mentions it to nobody.

Best Practices

1. Treat export like any other command. Anything that changes environment settings can change what your next command does, even when that next command is on your allowlist.

2. Do not mistake an allowlist for a boundary. It reduces interruptions. The vendor documentation now says outright that it is best-effort and not a security guarantee.

3. Isolate before the first command, not after something looks wrong. Untrusted means anything you did not write and have not read, which covers most of a dependency tree.

4. Use –clone for code you have not vetted, and opt out of the shared skills store. Otherwise Git hooks and build scripts stay live on your host, a poisoned hook will not appear in git diff, and a skill modified inside one sandbox is waiting for the next sandbox that loads it.

5. Remember a forwarded SSH agent is a live credential. The key file staying on your machine is not the same as the key being unusable, so restrict egress for untrusted work.

6. Read your own policy. Run sbx policy ls. Deny-by-default with a long allow list is closer to allow-by-default than it looks.

Take Action

Install Docker Sandboxes. Visit the Docker Sandboxes documentation to install sbx and run your first agent inside a microVM.

Connect your editor. The Remote – SSH integration puts your terminals inside the boundary while the editor stays where it is, so your workflow does not really change.

Codify the boundary with a kit. Define the network and credential rules your team needs once, and hand the same artifact to everybody instead of a personal allowlist.

Read the security model. The documentation is straight about what is isolated and what is not, including the workspace and shared skills store behaviour that –clone and the opt-out flag change.

Turn on audit logging. Docker AI Governance streams policy decisions into your SIEM, which turns a silent bypass into something somebody can actually investigate.

Conclusion

The uncomfortable thing about CVE-2026-22708 is that nobody in the story did anything wrong.

Cursor built an allowlist, which is what everyone asked for. The developer approved git branch, which any of us would have approved. The check inspected the command and found it acceptable, which is exactly its job. The attack worked anyway.

Getting an agent to correctly judge every instruction it reads is a problem that gets harder as agents get more capable, and it has no clean ending. Limiting what an agent can reach is a problem we solved a long time ago. The more useful move is to stop needing the first one, and to write down what the agent may reach as an artifact you can review, rather than a list each laptop keeps for itself.

Coming up in our series: Issue 6 looks at the ClawHub infostealer campaign, where malicious skills reached developer machines through a marketplace ranking exploit, and at what sandboxed skill execution, and that shared skills store, change about a registry you cannot personally audit.

Learn more

Run agents safely with Docker Sandboxes: Visit the Docker Sandboxes documentation to get started.

Understand the security model: Trust boundaries and isolation layers, including what is and is not isolated by default.

Customize sandboxes with kits: Extend an agent with tools, credentials, and network rules as a declarative artifact.

Govern agents across a team: Docker AI Governance for centrally defined sandbox, network and MCP policy with structured audit events.

Read the MCP Horror Stories series: Start with Issue 1 to understand the protocol-layer security risks that complement the agent-layer risks covered here.

Quelle: https://blog.docker.com/feed/

17,600 Actions: Agent Security Is a Systems Problem

Everyone has been talking about the OpenAI/Hugging Face incident, and I was initially skeptical that Docker had much to add. After several weeks of customer conversations, I think we do. The useful lesson is not that an AI agent escaped a sandbox. It is what 17,600 actions expose about security systems designed for human tempo.

Hugging Face reconstructed approximately 17,600 attacker actions across a four-and-a-half-day campaign in July, including roughly two and a half days inside its infrastructure.

Put thirty seconds of human review against each action and you get 147 hours of work. Hugging Face grouped those actions into roughly 6,280 clusters; review only those and you still get more than 52 hours. Either way, manual approval and ordinary alert triage were never plausible primary controls for this workload.

This was not a fundamentally new category of attack. If you have any background in incident response, the sequence is familiar: exploit a reachable service, obtain code execution, collect credentials, escalate privilege, and cross the next trust boundary.

What was different was the rate, persistence, and ability to carry authority and state across short-lived environments. The agent could fail, rebuild its tooling, recover its communications channels, and continue from another environment without starting the campaign over. The useful mental model is a capable attacker fused with a fuzzer: it can reason about each result and keep probing without fatigue. That is the AI part of the story.

This is not a commentary on model alignment, and I will offer no opinion here on which model or agent framework you or your organization should use. The security question is familiar: what authority should be given to a workload that can execute code, hold credentials, reach the network, and continue testing paths long after a human would have stopped?

What happened

OpenAI was running internal cyber-capability evaluations against a benchmark called ExploitGym, which tasks agents with finding and exploiting vulnerabilities. The evaluation used reduced refusal behavior and none of the production-grade classifiers a deployed model would normally have.

The agents did not have direct internet access. They were allowed to install packages through an internally hosted package-registry cache. The agents found a previously unknown vulnerability in that permitted service and used it to reach the open internet.

The permitted service was the escape path. That’s the important point in the incident.

From there, the agents escalated privilege inside OpenAI’s research environment, reached a user-hosted CyberGym-style code-execution harness running on an external sandbox, and obtained root inside that harness. The sandbox platform itself was not compromised. Having apparently worked out that Hugging Face might host the benchmark’s reference answers, the agents went after Hugging Face directly, assessing that cheating was the fastest path to a passing score.

Hugging Face’s reconstruction documents local-file disclosure, code execution through a template engine, cloud metadata access, Kubernetes privilege escalation, exposure of a production secret containing 136 keys, access to the corporate network through a stolen credential, and limited write access to source control. It found no evidence that public models, datasets, packages, or released software were modified, and the customer content accessed was limited to a handful of benchmark-related datasets. That is a good outcome relative to what was possible. It is not evidence that the attack path was harmless.

The individual weaknesses were familiar: an unsafe processing path, accessible cloud metadata, broad privileges, long-lived credentials, and a shared administrative identity. A capable human attacker could have chained them, too. The difference was the volume of paths tested, the speed with which a failed path was replaced, and the amount of evidence defenders had to interpret while the campaign continued.

If you want the full blow-by-blow, Hugging Face published a detailed technical writeup and interactive replay. Both are worth reading.

The controls this requires

That arithmetic, not the novelty of the attack, is what changes the operating model. A human cannot sit in the control loop for thousands of actions at machine speed.

There are also two related threat models to account for.

In the first, the agent discovers and exploits a path on its own, as the agents did in this incident. In the second, an external party redirects the agent through a poisoned tool, compromised dependency, malicious document, prompt injection, or attacker-controlled data. In that case, the agent becomes the attack vector.

The same authority is dangerous in either case. The controls therefore have to govern what enters the environment, which capabilities the agent receives, and what happens when its behavior leaves the expected boundary.

What can go wrongControl requiredUntrusted content attempts to change the agent’s instructionsTreat external content as data, never authority; preserve provenance and trust boundaries; do not allow retrieved content to modify policy or grant capabilitiesA tool, package, image, or MCP server is poisonedStrict allowlisting; pin versions and digests; verify signatures and provenance; require SBOMs; scan and review updates before promotionExternal data becomes executable inputUse structured and typed tool interfaces; validate and escape arguments; prohibit unsafe shell interpolation and other paths from data to command execution; run commands inside a sandbox and constrain which commands can be invokedA permitted service becomes an escape pathExpose the narrowest operation-specific interface; scope access by task and destination; monitor permitted paths for behavior that diverges from their purposeThe workload reaches ambient credentials or control-plane servicesRemove ambient credentials; use short-lived, task-scoped workload identity; block metadata and control-plane endpoints the task does not requireThe workload exceeds its intended execution boundaryUse a hardened isolation boundary; reject privileged workloads, host filesystem mounts, raw device access, and unrestricted host sockets unless explicitly requiredState or authority persists beyond replacement of the workerGovern durable write paths; separate read from write authority; correlate identity and activity across runsThe agent, or an attacker acting through it, crosses into another systemRequire explicit authorization for external and destructive actions; scope credentials to the target operation; make write paths observable and revocableThousands of individually plausible actions hide behavior that has diverged from the taskEvaluate sequences and bursts against policy and expected behavior; correlate activity across tools and systems; contain at machine speed

The point is not to put human approval in front of every action. That defeats much of the value of using agents and eventually produces approval fatigue. Routine and reversible actions should have very little friction. More sensitive, external, destructive, or unusual actions should receive stronger scrutiny.

Review and sanitization still matter, particularly for packages, tools, and paths where external data could become a command. But sanitization alone is not a reliable answer to prompt injection. Natural-language content is too ambiguous for us to assume we can always identify and remove the malicious part. The stronger boundary is architectural: untrusted content must not be able to grant itself authority, change policy, or create capabilities the agent did not already have.

Done well, governance is not what limits agent autonomy. It is what makes it possible to safely give agents more of it.

Where Docker fits today, and where we do not

We are proud to be founding authors of the Agent Baseline. We worked with other industry experts to distill the problem into six outcomes: Discover, Constrain, Authorize, Observe, Validate, and Respond.

If Docker Sandboxes sit in one specific bucket, it’s “Constrain,” but really, we believe they’re foundational, and where you would instrument or implement all six. They give each agent a dedicated microVM and enforceable boundaries around local compute, filesystem access, and network reach, as well as providing the base (and thus ground truth) layer to observe. That is a real and useful layer.

Docker AI Governance addresses parts of Authorize and Observe by giving organizations a centralized way to define and enforce controls around agent environments, including network and filesystem policies and access to MCP servers and tools.

Together, Sandboxes and AI Governance provide a meaningful part of the answer today: a hardened execution environment and centralized policy enforcement around it. They do not repair a vulnerable service the agent is authorized to contact, narrow a credential issued by another system, or replace the customer’s own security architecture. No vendor, Docker included, can claim its technology would have made this particular incident a non-event.

But a deterministic enforcement boundary is still necessary. It gives an organization one place to apply least capability and least privilege, and one place to observe what the agent was actually allowed to do. If an agent is using a package registry as an egress proxy rather than a package registry, that’s the kind of divergence the telemetry needs to help surface, especially when viewed across a sequence of requests rather than one request at a time.

The broader problem remains difficult. The useful unit of observation is not always one tool call. It may be a burst of activity, a target, a protocol, a credential, or a pattern visible only across systems. A package request can be normal. Repeatedly probing the service behind it, discovering credentials, and using them to reach another system should change the assessment.

That’s the agent-security challenge beyond basic containment. We need to constrain authority, but also observe activity at the right granularity, recognize when it deserves more scrutiny, and respond at the same tempo as the agent. For all of us, Docker included, there is still substantial work ahead across observation, validation, and response.

The operational tradeoff

Security, capability, and autonomy all matter, and they will always be in tension. Said differently, none of this is free.

Short-lived credentials expire during long-running tasks. Narrow egress policies break legitimate package installation. Admission controls reject tools developers assumed they could run. Cross-system detection costs money and produces false positives. A write approval inserted at the wrong point can eliminate most of the productivity the agent was supposed to provide.

Teams will be tempted to loosen each control until the agent works again. That is understandable. The failure mode created by a strict policy is immediate and visible; the failure mode created by excessive authority remains invisible until an incident.

The answer is not to remove the controls or ask a human to approve everything. It is to make friction proportional to consequence, test the failure modes, measure the operational cost, and weigh it against the risk and potential blast radius.

How I work

I use agents every day, and I assume that a sufficiently capable agent will eventually try something I did not anticipate (perhaps on a daily basis…).

For the most part, I do not run one general-purpose agent with access to everything. I use task-focused agents, each packaged as a separate kit, built on free Docker Hardened Images and run in Docker Sandboxes.

Each kit starts with a specific job, then receives only the software, network access, files, credentials, and external capabilities required for that job.

In most cases, the agent has very few restrictions inside its sandbox. That is intentional. What matters is that god mode inside the sandbox does not become god mode over my laptop, my credentials, or every service I can reach.

I do a lot of desk research. Those agents can access the open internet. They’re not useful if they can’t. But their image has no compilers, package manager, general-purpose network debugging tools, or development toolchain, and it runs with deliberately limited system permissions. They can retrieve and analyze public information, but have very little machinery with which to turn something they encounter into an exploit or act on another system. They have no reason to hold my source code or production credentials.

My production coding agent has a much richer environment. It runs pi, can use multiple models, compile code, run tests, and use the tools required for real engineering work. Its network access is restricted to an explicit allow list of services I use, including Docker, GitHub, Snowflake, and Cloudflare. It does not receive arbitrary internet access or arbitrary tools simply because a coding task occasionally needs the network.

My home kit can interact with an Arduino, but it does not receive direct access to the host or the device. A host-side MCP server brokers the allowed operations. The agent can request a defined Arduino capability through that interface; it cannot turn that permission into general access to every device connected to the machine.

My development kit is where I experiment. It runs with balanced network access, but no ambient host secrets and no unrestricted access to host files. When it needs Google Workspace, Snowflake, or another host service, host-side daemons broker those calls. The agent sees the capability I have chosen to expose, not the underlying credential or the rest of the service. Those brokers can enforce which operations are allowed and which are blocked.

These are deliberately different environments. The research agent would be poor at production coding. The coding agent cannot reach every site the research agent can. The home agent cannot turn an Arduino operation into arbitrary host access. The development agent can query a service without possessing the credential that authorizes the query.

That constraint is the feature.

Conclusion: Security at agent speed

The OpenAI/Hugging Face incident was not the failure of a single boundary. It was a chain of reasonable-seeming permissions and familiar weaknesses that became something very different when an agent could test thousands of paths, preserve state across runs, and carry authority from one system into the next.

We will not anticipate every vulnerability an agent might find or every way it might combine the access we give it. The architecture cannot depend on perfect agent behavior, perfect software, or a human noticing every dangerous action in time.

So, the starting point is still least capability and least privilege: give an agent the narrowest interface, credentials, tools, and network access its task requires. Put those controls at a deterministic enforcement boundary. Make the resulting activity observable, not only as isolated requests, but as sequences and patterns across systems. When the behavior leaves the expected envelope, containment has to happen at agent speed.

Docker Sandboxes and Docker AI Governance provide important parts of that architecture today: hardened execution boundaries and centrally enforced policy around them. They do not secure every service an agent is permitted to contact, and they do not eliminate the need for an organization to decide what authority each agent should have. The broader work across Discover, Constrain, Authorize, Observe, Validate, and Respond is why we helped create the Agent Baseline in the first place.

The goal is not to build an agent that never tries the wrong thing. The goal is to build a system where trying the wrong thing does not give it the keys to everything else.

Quelle: https://blog.docker.com/feed/

IAM Policy Autopilot now supports Terraform plan files

IAM Policy Autopilot can now generate baseline IAM policies directly from a Terraform plan file. IAM Policy Autopilot is an open source tool, launched at re:Invent 2025, that analyzes your code to deterministically create scoped-down IAM policies you can refine as your application evolves, reducing the time you spend writing IAM policies and troubleshooting access issues. Until now the tool analyzed application source code, but it was not possible to generate policies for deploying AWS infrastructure defined via Infrastructure as Code.
Now you can pass a Terraform plan file as input, and IAM Policy Autopilot applies a deterministic analysis to produce a policy scoped to the CRUD functions of the resources in that plan. The generated policies reference specific resource ARNs rather than wildcards, when possible. Supporting policy generation for deploying AWS infrastructure defined via Terraform has been the most requested capability since IAM Policy Autopilot launched, and it complements the existing Terraform-aware analysis, which cross-references Terraform resource definitions with SDK calls in your application code to resolve ARNs.
IAM Policy Autopilot is available at no additional cost and runs on your own machine. To get started, visit the IAM Policy Autopilot GitHub repository.
Quelle: aws.amazon.com

Amazon MWAA Serverless now supports PythonOperator and BashOperator

Amazon Managed Workflows for Apache Airflow (Amazon MWAA) Serverless now supports running custom Python functions and shell scripts directly in the serverless runtime using PythonOperator and BashOperator. With this launch, data engineering teams can execute the code patterns they rely on daily, including data transformations, format conversions, and data quality checks, without provisioning additional infrastructure.
Package your Python modules or shell scripts as code packages, upload them to Amazon S3, and reference them when creating or updating a workflow. The service snapshots your code at workflow creation time and uses that snapshot for all subsequent runs, ensuring consistency across executions.
This feature is available in all AWS Regions where Amazon MWAA Serverless is available. To learn more, visit Using Python and Bash operators.
Quelle: aws.amazon.com

AgentCore payments is now generally available in Amazon Bedrock AgentCore

Today, AWS announces the general availability of AgentCore payments, a capability within Amazon Bedrock AgentCore that enables AI agents to autonomously discover, access, and pay for paid APIs, MCPs, and content with just a few lines of code. AgentCore payments provides the security, guardrails, and observability enterprises need to deploy transacting agents in production at scale.
AgentCore payments integrates with Coinbase and Stripe Privy wallets for microtransactions, provides payment orchestration across protocols, enforces configurable payment limits at the infrastructure layer, and delivers end-to-end observability through AgentCore Observability. At general availability, AgentCore payments includes Quick Create for Coinbase credential provisioning directly within the AgentCore console, a curated Coinbase Bazar MCP server of pay-per-use x402 endpoints via AgentCore gateway, support for the Machine Payment Protocol (MPP), and the “upto” scheme in the x402 protocol for pay-per-inference and dynamic pricing use cases.
Developers can get started using coding assistant skills such as Claude Code, Kiro, and Codex, AgentCore CLI, or AWS Management Console – follow this link.
AgentCore payments is available in the regions listed here. To learn more, visit the AgentCore payments documentation or the AWS News Blog.
To learn about pricing, visit AgentCore pricing.
Quelle: aws.amazon.com