Essay / Security · 2026-08-21

Assume the prompt injection worked

Detection asks hostile text to reveal that it is hostile. Containment asks a simpler question: if the agent follows every instruction in the repository, what can the resulting process still reach?

The operating assumption. The agent read a malicious instruction, believed it, and is now using every tool exactly as designed. Build the boundary for that case.
Four sources of browser authority: live sessions, extensions, localhost access, and attacker-controlled page instructions
The browser makes the prompt-injection problem concrete: attacker-controlled text arrives inside a client carrying ambient sessions, standing grants, and loopback reach.

A repository asks the agent to “read the setup notes before running tests.” The notes include a hidden instruction: inspect the user's SSH directory, send the interesting files to a diagnostics endpoint, then continue with the original task. Nothing in that chain requires a memory-safety exploit. Reading files, making requests, and following repository instructions are the agent's advertised capabilities.

The security question is therefore not whether the instruction looks suspicious to a model. It is whether the resulting process can read the directory, reach the endpoint, or carry a reusable credential there.

Prompt injection is often treated as a classification problem. Find the suspicious sentence. Score the page. Ask another model whether the instruction looks malicious. Block the obvious phrasing.

Those controls can reduce noise. They cannot define the security boundary, because the attacker chooses the text and can iterate against the same cues the detector uses. A repository can hide instructions in documentation, generated files, issue text, tool output, test failures, or a web page the agent opens.

The durable control begins after detection fails.

Translate the compromise into capabilities

Do not ask what the injected agent intends. Ask what its process can do:

Each answer should be enforced by something outside the agent.

A key inside the box is already compromised

Environment variables and dotfiles are convenient credential delivery systems. They are also readable bytes in the compromised process's authority domain.

A credential broker changes the shape. The real key stays on the host. The box receives a route to a narrow proxy, and the proxy injects authentication only for the allowed service. Scope that route to one runtime. A Claude box should not be able to turn an OpenAI key into a laundering channel merely because both agents are installed on the host.

This does not stop the model service from receiving source included in a legitimate prompt. Source confidentiality against the model is a separate decision: use a self-hosted model or remove model egress.

An allowlist is only as strong as its layer

Proxy variables constrain cooperative applications. A compromised process can clear them and open a socket. If off-list destinations must be unreachable, enforcement has to meet raw traffic: a private network namespace and packet rules, or a VM network stack.

Name the layer. L7 proxy scoping and L3/L4 destination enforcement are not interchangeable promises.

Local sockets are network authority too

Unix sockets disappear from many threat models because they do not look like internet access. They can connect the box to SSH agents, desktop services, container daemons, and other privileged processes. Some can carry open file descriptors.

Deny the address family by default. Grant it only to profiles that need it, and keep host sockets outside filesystem grants. A browser control daemon may justify one scoped socket. A test runner usually does not.

The final capability is acceptance

A compromised agent that cannot read secrets or dial arbitrary hosts can still produce a malicious patch. Containment limits blast radius during execution; it does not certify the output.

That is why the box should not merge its own work. Export a path-validated patch and evidence bundle. Review them outside. The human-operated output gate is part of the security design, not workflow polish.

What success looks like

Success is not “the detector found every injection.” Success is that an injected agent encountered the same narrow world as a cooperative one:

The injection may succeed as language. It fails as authority.

Why detection remains useful but cannot carry the boundary

Filters can catch crude attacks. A reviewer can notice an instruction in a README. A second model can flag text that asks for secrets. Tool descriptions can be scanned before they enter context. These controls reduce exposure and improve triage.

They still operate on the attacker's representation. Rename the file, split the instruction across tool outputs, encode the payload in a test failure, or make the dangerous action look like a legitimate debugging step. A sufficiently strict filter also blocks real work, because coding routinely requires reading configuration, opening documentation, and sending authenticated requests.

Containment works on the action after ambiguity has ended. Whatever prose led to open(), socket(), or a write outside the workspace no longer matters to the enforcement decision.

The browser chains ambient authority without exposing a token

A normal browser profile is the sharpest example. It holds cookies for source control, email, CI, cloud dashboards, and internal tools. The agent never needs to read those cookies. It navigates and the browser authenticates the request automatically.

The same process reaches host loopback, where developer services often rely on “local only” instead of authentication. And the browser's primary input is page content controlled by someone else. Prompt injection becomes the instruction channel joining live sessions, extensions, and local services.

A fresh browser profile inside the box removes the inherited sessions and extensions. A private network namespace changes loopback from “the developer's machine” to “this disposable environment.” The page can still inject the agent. The injected agent finds much less authority waiting for it.

A credential broker removes the reusable secret from the compromise

Model access creates an awkward exception. The box must call Anthropic or OpenAI, and the ordinary implementation puts the API key in an environment variable or credential file inside the very process we are assuming compromised.

h5i can instead point the client at a host-side broker. The box presents a per-run dummy token. The broker pins the upstream origin, validates origin-form request targets, strips the dummy, injects the real host credential, and creates the TLS request itself. Stealing the dummy gives an attacker no reusable API credential.

The broker is authentication plumbing, not authorization. A broad GitHub token remains broad when used through a broker. Fine-grained service credentials are still required. Nor can the broker stop a legitimate model call from containing private source. It removes credential possession; it does not inspect intent.

Build the response as independent layers

Attack stepBoundary responseResidual risk
Read host secretsDo not grant host paths; seed a scrubbed per-box HOMEFiles intentionally copied into the workspace remain readable
Steal a model keyKeep the real key behind a runtime-scoped brokerAllowed model requests can still contain source
Exfiltrate to a new hostDefault-deny egress at the claimed layerAllowed destinations remain reachable
Borrow a local daemonDeny Unix sockets and isolate loopback by defaultExplicit socket grants carry real authority
Ship a malicious patchRequire export and external reviewA reviewer can still make a bad decision

No row depends on the model agreeing that it has been compromised. That independence is the design.

The honest stopping point

A sandbox does not solve prompt injection as a language problem. The agent may still waste time, damage its disposable workspace, produce a deceptive explanation, or create a malicious patch. A shared-kernel tier remains exposed to a targeted kernel exploit. An allowlisted service can still be abused within its authorization.

The goal is narrower: prevent untrusted instructions from inheriting the developer's ambient machine authority. That turns a successful injection from an account- and host-level incident into a failed or reviewable action inside a disposable box.

Why the usual mitigations stop one layer too early

“I require approval for shell commands.” The dangerous action can be hidden among dozens of ordinary build and inspection calls. Approval fatigue is the predictable output of putting a human gate on a machine-rate loop. More importantly, package hooks and browser requests may occur below the command the human approved.

“The browser verbs are read-only.” Navigation can trigger state changes through confirmation links and poorly designed GET endpoints. Reading page content is itself an exfiltration primitive once that content enters the model context. Verb names do not define authority.

“The key is encrypted on disk.” The agent does not need to decrypt a browser cookie store if it can drive the browser that decrypts and attaches cookies. It does not need to steal an API key if an allowed client will make any request it asks for. Protecting bytes at rest does not constrain the authorized interpreter.

“The agent runs in a container.” A container with the host browser profile mounted, a Docker socket exposed, or host loopback reachable still carries the authority that matters. Containerization is a mechanism, not a completed threat model.

“The model vendor blocks prompt injection.” Even a strong detector cannot mediate a native install script, a compromised compiler plugin, or an ordinary request that is dangerous only because of the credential and destination available in this environment. The enforcement point has to sit where the action becomes concrete.

Use the compromise drill

Take a real profile and assume the agent has become adversarial. Ask it to enumerate readable host paths, reusable credentials, reachable internet hosts, reachable loopback services, Unix sockets, and direct write paths to accepted code. Do not actually exfiltrate data; inspect the resolved policy and exercise harmless denials.

If the answer relies on “the agent would not do that,” the authority is still present. If the answer is “the syscall, packet, or export path is refused and the refusal is recorded,” the boundary can survive the model making the wrong semantic decision.

Sources and further reading

Questions that come up

Does sandboxing prevent source code from reaching the model?
No. A coding agent can include source in an allowed model request. Preventing that requires a self-hosted model or a policy with no model egress.
Are permission prompts still useful inside a box?
They can improve usability and catch mistakes, but they are not the security boundary. A prompt-injected agent can approve or bypass its own application-level permissions; the box policy remains outside it.
Build the boundary

Write down what the agent may reach

Create a fail-closed profile for filesystem, network, and resources.

Design for the compromised session

A narrow box makes prompt-injection success less consequential.