DEV Community

Zira
Zira

Posted on

Your AI Agent Is Not Isolated Until You Test These 7 Escape Paths

An agent can run in a container and still have more authority than you intended.

The usual mistake is treating "the process is in a container" as equivalent to "the agent is isolated." Those are different claims. The process may still inherit credentials, reach a metadata endpoint, talk to a host socket, reuse a browser profile, or leave child processes behind after the run ends.

This article gives you a repeatable escape-path test for coding agents, OpenClaw-style browser workers, and local automation that may execute untrusted or model-generated steps.

Start with an explicit boundary

Write down the boundary before choosing tools:

Surface Allowed Denied Evidence
Filesystem disposable workspace host home, SSH keys, cloud credentials mount table and file probes
Network approved API hosts metadata, private ranges, arbitrary egress connection log
Processes one worker tree host PID namespace, detached children process snapshot after teardown
Identity one short-lived run identity developer shell identity environment and token audit
Browser fresh profile per run personal profile, saved cookies profile path and cookie check

If you cannot state the allowed side and the denied side, you cannot verify the boundary.

The seven escape paths

Test these independently. A passing container health check does not cover them.

  1. Credential inheritance. Check environment variables, mounted files, SSH agents, cloud metadata, and credential-helper sockets.
  2. Filesystem reachability. Probe parent directories, mounted volumes, proc, sys, and temporary files from previous runs.
  3. Network reachability. Try DNS, private IP ranges, link-local metadata addresses, Unix sockets, and direct-IP connections that bypass hostname rules.
  4. Process escape. Start a child process, daemonize it, close the parent, and verify that teardown removes the whole process group.
  5. Browser reuse. Confirm that a new run cannot see cookies, storage, extensions, downloads, or a debugging port from another profile.
  6. Control-plane confusion. Ensure the supervisor cannot be invoked through the same tool path it is meant to supervise.
  7. Evidence loss. Preserve the command, decision, target, run ID, and result for every denied probe. A silent deny is hard to audit.

A minimal probe contract

Make every probe return a structured result instead of a shell exit code alone:

{
  "probe": "credential-file",
  "target": "home/.ssh/id_ed25519",
  "decision": "DENY",
  "observed": "ENOENT",
  "run_id": "test-2026-08-08-001",
  "evidence": "sha256:..."
}
Enter fullscreen mode Exit fullscreen mode

Use DENY, ALLOW, and UNKNOWN as separate states. UNKNOWN means the test could not establish the boundary and should fail closed for a production rollout.

Run the probes from inside the worker

The test should execute with the same UID, mounts, environment, network policy, and browser launcher as the real agent.

set -eu

printf '%s\n' '== identity =='
id
printf '%s\n' '== mounts =='
cat /proc/self/mountinfo | sha256sum
printf '%s\n' '== sensitive environment names =='
env | grep -E 'AWS_|AZURE_|GCP_|SSH_|TOKEN|SECRET|COOKIE' || true
printf '%s\n' '== likely credential paths =='
for p in home/.ssh home/.aws /var/run/secrets /run/host-services; do
  test -e "$p" && echo "VISIBLE $p" || echo "DENIED $p"
done
printf '%s\n' '== process tree =='
ps -eo pid,ppid,pgid,comm
Enter fullscreen mode Exit fullscreen mode

Do not print secret values. Record only presence, ownership, permissions, and a digest of non-sensitive evidence.

Test network policy as a matrix

A single request to the public internet proves very little. Use a matrix with expected outcomes:

Target Expected
approved API hostname ALLOW
its resolved public IP ALLOW or explicit DENY, by policy
loopback addresses DENY
RFC1918 private ranges DENY unless explicitly required
link-local metadata address DENY
arbitrary DNS name DENY or policy decision
host Unix socket DENY

Log both the requested target and the resolved target. Otherwise a hostname allowlist can hide a DNS rebinding or direct-IP gap.

Teardown is part of isolation

The boundary is not proven when the command returns. Inject a failure after each of these points:

  • after a child process starts
  • after a browser launches
  • after a credential is mounted
  • after a network lease is created
  • after the agent is killed but before the supervisor records completion

Then verify that the process group, browser profile, temporary credentials, network lease, and queued tool calls are gone. A restart must not inherit a half-cleaned run.

The result you want is not just an exit code of zero. It is a teardown record with the run ID, surviving PIDs, remaining mounts, open sockets, browser profile path, and cleanup decision.

A practical rollout checklist

Before allowing an agent to handle real repositories or accounts:

  • [ ] No developer credentials are inherited by default.
  • [ ] The workspace is disposable and its mount list is recorded.
  • [ ] Network policy is tested by hostname, resolved IP, and private-range probes.
  • [ ] The worker and every child process share a tracked process group.
  • [ ] Browser state is fresh, scoped, and destroyed after the run.
  • [ ] Denials produce evidence without exposing secrets.
  • [ ] UNKNOWN blocks promotion rather than being counted as a pass.
  • [ ] Failure injection proves cleanup after crashes, timeouts, and supervisor restarts.

The useful question is not "Which sandbox product should I choose?" It is "Which authority can this agent still reach, and what evidence proves it cannot reach the rest?" That question produces a boundary you can review, reproduce, and rebuild.

If this control-plane approach is useful, follow for more implementation-focused notes on agent reliability, recovery, and deployment.

Top comments (0)