# AI Agent Sandboxes Stop Escapes. They Don't Tell You What Happened Inside

> Source: <https://rye.ai/blog/ai-agent-sandboxes-ebpf-runtime-visibility/>
> Published: 2026-08-12 20:25:22+00:00

Articles

# AI Agent Sandboxes Stop Escapes. They Don't Tell You What Happened Inside.

Docker Sandboxes and microVM isolation keep AI agents away from the host. They do not tell security teams what the agent read, ran, changed, or sent while it was inside.

Docker just shipped [Docker Sandboxes](https://www.docker.com/products/docker-sandboxes/). It runs AI coding agents such as Claude Code, Codex CLI, Copilot CLI, Kiro, and OpenCode inside dedicated microVMs using a [custom VMM](https://www.docker.com/blog/why-microvms-the-architecture-behind-docker-sandboxes/) built for cross-platform support on macOS, Windows, and Linux. Each sandbox gets its own kernel, a mounted workspace, and a network policy that only allows approved hostnames. The workspace mount is live on your host filesystem throughout the session. VM state - installed packages, shell history, files written inside the VM - persists across restarts and is discarded only when the sandbox is explicitly removed.

For developers running agents in YOLO mode (`--dangerously-skip-permissions`

), this is a real improvement. If the agent goes sideways, the host should stay clean.

But a sandbox only answers one question: did the agent get out?

Most teams will need a different answer first: what did the agent do while it was in there?

[Why Containers Were Never Enough](#why-containers-were-never-enough)

Before Docker Sandboxes, the usual advice was to put the agent in a Docker container. Mount only the project directory. Delete the container when the job is done. That sounds cleaner than it is.

Docker containers share the host kernel. Namespaces and cgroups help, but the same kernel still enforces the boundary. Container escapes are a recurring class of CVE: [CVE-2019-5736](https://ubuntu.com/security/CVE-2019-5736) for runc overwrite, [CVE-2022-0492](https://ubuntu.com/security/CVE-2022-0492) for cgroup escape, [CVE-2024-21626](https://ubuntu.com/security/CVE-2024-21626) for runc again. None of these are casual attacks. Still, an AI agent manipulated through [prompt injection](/blog/ghostapproval-vulnerability-ai-coding-assistants/) is not a process I would trust by default.

Firecracker microVMs change the shape of the risk. Each sandbox runs its own Linux kernel and is isolated from the host by [KVM](https://linux-kvm.org/page/Main_Page). A guest kernel bug should not become a host kernel bug. This is the same basic isolation model used by [AWS Lambda](https://aws.amazon.com/blogs/aws/firecracker-lightweight-virtualization-for-serverless-computing/) and [Fly.io](https://fly.io/blog/sandboxing-and-workload-isolation/) machines, where untrusted customer code runs on shared hardware.

So the isolation primitive is the right one.

| Isolation model | Shared host kernel | Hardware boundary | Typical startup |
|---|---|---|---|
| Docker container | Yes | No | ~50ms |
|

The problem starts after the boundary holds.

[What a Sandbox Actually Stops](#what-a-sandbox-actually-stops)

It helps to be precise. A microVM sandbox with network policy narrows these attack surfaces:

**Host filesystem access.** The agent can only see and write the project workspace that was explicitly mounted. It cannot read `~/.ssh/`

, `~/.aws/credentials`

, your shell history, or any other file on your machine.

**Host process access.** The agent cannot see or signal host processes. It cannot attach a debugger to your IDE, kill your VPN client, or tamper with other running agents.

**Lateral network movement.** With a deny-all-except-allowlist network policy, the agent cannot reach your internal network, your cloud metadata endpoint (`169.254.169.254`

), or arbitrary internet infrastructure. It can only talk to the domains you approved.

**VM-layer persistence on dispose.** When the sandbox is explicitly removed, installed packages, shell history, and files written inside the VM outside the mounted workspace are discarded. The workspace itself is a live mount - the agent reads and writes your host files directly throughout the session, not copies. VM state persists across restarts until you run the dispose command.

Those controls matter, especially for unattended jobs: nightly refactors, CI code review agents, and autonomous test generation. I would rather run those in a microVM than on a developer laptop.

[What a Sandbox Does Not Stop](#what-a-sandbox-does-not-stop)

The sandbox boundary is the microVM perimeter. Inside that perimeter, you still have a busy little machine doing real work.

**You have no audit trail of agent actions.** The agent reads files, writes files, runs shell commands, and opens network connections. The sandbox does not record that in a structured log outside the [agent's own session log](/blog/how-ai-coding-agents-actually-run/). That log is inside the sandbox and controlled by the agent process. If the agent deletes it before the session ends, the record goes with it.

**The agent can still damage the project.** A prompt-injected agent can delete the workspace, overwrite config, push to git remotes if credentials are mounted, or send source code to an allowed hostname. The sandbox stopped it from reaching the host. It did not stop it from using the access you gave it.

**The network allowlist is blunt.** If `api.github.com`

, `registry.npmjs.org`

, or `pypi.org`

are allowed, and they probably are for real development work, a malicious install or compromised remote has a valid path out. The allowlist blocks random attacker infrastructure. It does not block misuse of channels that are supposed to be open.

**You cannot reconstruct what happened after the fact.** If a sandbox session produces unexpected output, deletes files, or commits surprising code, you have no kernel-level record to audit. The agent's session log, if it exists and was not tampered with, tells you what the model intended. It does not tell you what actually executed at the syscall level.

That is the blind spot. Docker Sandboxes can do its job perfectly and still leave you unable to explain an incident.

[What eBPF Sees](#what-ebpf-sees)

[eBPF](https://ebpf.io/what-is-ebpf/) sounds like kernel trivia until you need a trustworthy activity log. It lets you attach small programs to kernel events such as syscall entry and exit, network connections, and filesystem operations. Tools like [Cilium Tetragon](https://tetragon.io/) and [Falco](https://falco.org/) use it to produce structured events for what a process actually does.

For **containers**, this works from the host. Because the container shares the host kernel, Tetragon or Falco running on the host sees every syscall the agent makes:

- Every
`open()`

,`read()`

,`write()`

,`unlink()`

call, with the full resolved path - Every
`execve()`

- every subprocess spawned, with its argv - Every outbound TCP connection, with destination IP and port
- Every
`connect()`

to a Unix socket - Every
`clone()`

or`fork()`

- every child process

This is not sampling. Events are generated synchronously with the kernel events themselves. The agent cannot suppress or delete them - the record is written before the syscall returns.

**For microVMs, the picture is different.** Guest syscalls trap to the guest kernel. KVM only surfaces VM-exits to the host. Host-side kprobes and tracepoints cannot see guest VFS paths, file names, or PIDs - there is no shared kernel for them to attach to. To get the same syscall-level telemetry inside a microVM, eBPF has to run inside the guest, or you rely on telemetry at the VMM boundary, the workspace mount layer, or hooks the sandbox runtime itself provides. The tamper-resistance property still holds when the telemetry agent runs at higher privilege than the workload, but the deployment is more involved than dropping a DaemonSet on the host.

[What a Complete Audit Trail Looks Like](#what-a-complete-audit-trail-looks-like)

Here is the kind of Tetragon output I would want from a Claude Code session - produced by in-guest Tetragon for a microVM, or host-side Tetragon for a container:

```
{"process": {"pid": 1847, "binary": "/usr/bin/node", "arguments": "claude --dangerously-skip-permissions"},
 "action": "open", "path": "/workspace/src/auth/session.ts", "flags": "O_RDONLY"}

{"process": {"pid": 1847, "binary": "/usr/bin/node"},
 "action": "open", "path": "/workspace/.env", "flags": "O_RDONLY"}

{"process": {"pid": 2103, "binary": "/bin/bash", "arguments": "npm install lodash-contrib"},
 "action": "connect", "destination": "104.16.1.35:443", "hostname": "registry.npmjs.org"}

{"process": {"pid": 2103, "binary": "/bin/bash"},
 "action": "execve", "path": "/workspace/node_modules/.bin/postinstall-hook", "arguments": ""}

{"process": {"pid": 1847, "binary": "/usr/bin/node"},
 "action": "open", "path": "/workspace/src/auth/session.ts", "flags": "O_WRONLY|O_TRUNC"}
```

From that stream, the incident questions get much less fuzzy:

- Did the agent read
`.env`

before modifying auth code? (Yes.) - Did a postinstall hook run after a package was installed? (Yes. What did it do next?)
- Did the agent open a file for writing that it did not have explicit instructions to modify?
- Did any subprocess attempt a connection to an IP not on the allowlist?

Those are normal incident questions. Without a separate event stream, the sandbox may disappear before anyone can answer them.

[Tetragon and Falco: Practical Starting Points](#tetragon-and-falco-practical-starting-points)

** Cilium Tetragon** is the stronger tool for this job. It supports

[resources, so you can choose the events you care about:](https://tetragon.io/docs/concepts/tracing-policy/)

`TracingPolicy`

`open`

, `execve`

, `connect`

, `clone`

, process binary filters, and structured JSON export. For containers it runs as a DaemonSet on the host or as a standalone binary. For microVMs it needs to run inside the guest, which means provisioning it as part of the VM image or sandbox startup script.A minimal Tetragon policy for AI agent sessions:

```
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
  name: ai-agent-audit
spec:
  kprobes:
    - call: "fd_install"
      syscall: false
      args:
        - index: 0
          type: int
        - index: 1
          type: "file"
      selectors:
        - matchBinaries:
            - operator: In
              values:
                - "/usr/bin/node"
                - "/usr/bin/python3"
                - "/bin/bash"
                - "/bin/sh"
    - call: "sys_execve"
      syscall: true
      args:
        - index: 0
          type: "string"
        - index: 1
          type: "string_array"
    - call: "tcp_connect"
      syscall: false
      args:
        - index: 0
          type: "sock"
```

** Falco** is easier to start with if it is already deployed. Its rule language is simpler, and the default rules catch plenty of strange behavior. The tradeoff is detail. Falco works at a higher level and can miss some syscall-level context. For AI agent workloads, where the interesting signal may be "read a credential file" or "spawned a weird subprocess," Tetragon's extra detail is usually worth the setup.

[Where This Leaves the AI Agent Security Stack](#where-this-leaves-the-ai-agent-security-stack)

A microVM sandbox and an eBPF audit layer address different parts of the threat model and should be used together:

| Layer | Tool | What it does |
|---|---|---|
| Isolation |
|

[Tetragon](https://tetragon.io/)/[Falco](https://falco.org/)(eBPF, in-guest for microVMs)[Docker AI Governance](https://www.docker.com/blog/docker-ai-governance/)/[OPA](https://www.openpolicyagent.org/)/[Rye](/)None of these layers carries the whole load. A sandbox without telemetry is a black box. Telemetry without containment lets you watch the damage happen. Agent permissions help, but they run inside the product you are trying to police. Policy without an audit trail is hard to defend after the fact.

At the application layer, [Rye](/) sits outside the agent runtime. It wraps CLI sessions, routes model traffic through a local policy proxy, records approval, file-change, and request metadata, and normalizes audit events across tools. Kernel telemetry answers what ran inside the sandbox; Rye connects that activity to the agent session, model request, policy decision, and workspace context.

The industry has spent a lot of energy on containment. Good. Now it needs visibility inside the contained environment.

The sandbox stopped the escape. The audit log tells you what actually happened.
