Anthropic's Claude Code CLI tool relies on a bubblewrap sandbox to contain the AI agent's system-level actions. A Time-of-Check Time-of-Use (TOCTOU) flaw in the sandbox's mount configuration meant that if .claude/settings.json did not exist when the sandbox launched, the file received no protection at all — allowing malicious code inside the sandbox to create it with injected SessionStart hooks that execute with full host privileges on restart. This is not a jailbreak or prompt injection against the model. It is a systems-level infrastructure bug in the tooling wrapper around the AI.
Claude Code's bubblewrap sandbox protected .claude/settings.json with a read-only bind mount — but only if the file already existed at startup. If it was absent, the sandbox's deny-path logic silently skipped the mount, leaving the path writable. An attacker who could execute code inside the sandbox — via a compromised dependency, prompt injection, or malicious repository — could create the file with a SessionStart hook containing arbitrary shell commands. The next time the developer started Claude Code, those hooks would fire outside the sandbox with full host privileges, achieving a complete sandbox escape and arbitrary code execution.
Bottom line: A single missing file turned a sandboxed AI coding agent into a persistence mechanism for arbitrary host-level code execution. Fixed in @anthropic-ai/claude-code v2.1.2.
GitHub's CVSS v4.0 assessment scores this vulnerability at 7.7 HIGH with vector CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N, reflecting the requirement for attacker-placed preconditions (AT:P) and passive user interaction (UI:P — the developer must restart Claude Code). NIST's v3.1 assessment scores it at 10.0 CRITICAL with AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H, emphasizing the scope change (S:C) from sandbox to host and the absence of authentication requirements.
Claude Code is Anthropic's official command-line interface for interacting with Claude as an autonomous software engineering agent. Unlike a chatbot that merely suggests code, Claude Code can read files, write to disk, execute shell commands, manage Git operations, install packages, and orchestrate multi-step development workflows — all directly on the developer's machine. It ships as an npm package (@anthropic-ai/claude-code) and is designed for professional software engineering at scale.
The tool operates under a permission model where developers grant or deny access to specific tools and commands. To contain the risk of the AI executing harmful shell commands, Claude Code wraps Bash execution in a bubblewrap (bwrap) sandbox on Linux — a namespace-based isolation layer that restricts filesystem writes and network access.
CVE-2026-25725 is not a jailbreak, prompt injection against the model, or a guardrail bypass. It is a systems-level infrastructure bug (CWE-501: Trust Boundary Violation) in the sandbox configuration logic. The AI model's safety layer is irrelevant to this exploit — the vulnerability exists entirely in the tooling wrapper's mount configuration code.
Bubblewrap (bwrap) is a lightweight, unprivileged sandboxing tool that uses Linux kernel namespaces to isolate processes. Unlike Docker, it does not require root privileges or a daemon — it creates ephemeral sandboxes at the process level. Claude Code's sandbox runtime (open-sourced at anthropic-experimental/sandbox-runtime) configures bwrap with the following namespace isolation:
Claude Code's sandbox applies an intentionally asymmetric filesystem access model. Read access uses a deny-specific approach: the sandbox mounts the entire host filesystem as readable, then blocks specific sensitive paths (like ~/.ssh, shell configs, and IDE settings) with read-only or null mounts. Write access uses an allow-specific approach: the entire filesystem is mounted read-only, and only the current working directory is bind-mounted as writable.
Because --unshare-net removes the network namespace entirely, Claude Code bridges network access through a proxy architecture: a socat Unix domain socket (bind-mounted into the sandbox) forwards traffic to host-side HTTP and SOCKS5 proxy servers that enforce domain allowlists and denylists. All outbound traffic from inside the sandbox must pass through this proxy layer.
The sandbox only covers Bash commands. Claude Code's Read, Write, Edit, Glob, and Grep tools execute in-process with fs.readFileSync and fs.writeFileSync — they have full host access with no sandbox isolation whatsoever. This architectural gap is documented in issue #26616 and represents a separate, fundamental attack surface.
When the bubblewrap sandbox initializes, it iterates through a list of mandatory deny paths — sensitive files that should be read-only regardless of user configuration. For each path, the code checked whether the file existed on disk. If it did, a read-only bind mount was applied. If it did not, the path was silently skipped with a debug log message.
This is a classic Time-of-Check Time-of-Use (TOCTOU) flaw. The check happens at sandbox startup; the use happens during the sandboxed session. If the file does not exist at startup but the parent directory is writable, any code running inside the sandbox can create the file freely — the deny rule never applied.
The .claude/ directory sits inside the project's working directory — which is the one path the sandbox mounts as writable. Certain files within it received explicit protection:
The settings.local.json file was always protected because it is typically created during Claude Code's first run. But settings.json is a project-level configuration file — many projects simply do not have one, and many developers never create one. In those cases, the sandbox offered zero protection.
The fix mounts /dev/null as a read-only bind at the first non-existent path component. This makes the missing file appear as an empty file, causing mkdir -p to fail when attempting to create the directory tree — effectively blocking creation of the entire path.
Claude Code's hooks system allows developers to define shell commands, HTTP endpoints, or LLM prompts that execute automatically at specific lifecycle events. Hooks are configured in settings.json files and fire without explicit user confirmation at runtime.
The SessionStart hook fires when a Claude Code session begins or resumes — including on startup, resume, clear, or compact operations. It requires no matcher (it fires on every session start), executes silently before any user interaction, and — crucially — runs outside the sandbox with full host privileges.
Every hook event executes outside the sandbox. This is by design — hooks are intended as a developer-controlled extension mechanism. But when an attacker can write to the settings file that defines hooks, this design becomes the escalation path from sandbox-contained code to unrestricted host execution.
Hooks are defined in .claude/settings.json — the same repository-controlled configuration file that the sandbox failed to protect. Any code inside the sandbox that could write to this path could define hooks that would execute shell commands on the host with the developer's full privileges on the next session start.
No public PoC was released (the vulnerability was reported via HackerOne private disclosure), but the exploit is trivially reconstructible. Inside the sandbox, the attacker needs only a file write:
Any mechanism that can execute code inside the sandbox can trigger this exploit:
postinstall script runs inside the sandbox during npm install. The script writes the payload as a side effect..claude/settings.json with hooks that execute on every developer's machine when they work with the project.The core fix (PR #80, stabilized in PR #126) introduces a findFirstNonExistentComponent() helper. When a deny path does not exist at startup, the sandbox now mounts /dev/null read-only at the first missing path component — blocking mkdir -p from creating the directory tree. A cleanupBwrapMountPoints() function tracks these mount points and removes them after sandbox exit if they are still empty, preventing ghost dotfiles on the host.
The fix was shipped in @anthropic-ai/claude-code v2.1.2. Users on standard auto-update received the patch automatically. The advisory was published on February 6, 2026.
CVE-2026-25725 is not an isolated incident. A systematic review of Claude Code's public issue tracker reveals a pattern of file access control failures, sandbox escapes, and catastrophic data losses that spans the tool's history.
CVE-2026-25725 was disclosed alongside 13 other CVEs affecting Claude Code in the same version range. The batch spans command injection, symlink bypasses, trust boundary violations, and data exfiltration — reported by security researchers from NVIDIA, SpecterOps, GMO Flatt Security, and multiple HackerOne contributors.
.claude/settings.json in any project directory — especially if the file previously did not exist
SessionStart hooks in any settings.json containing shell commands (curl, wget, bash, pipe operators)
.claude/settings.json files across repositories for unexpected hook definitions
@anthropic-ai/claude-code v2.1.2 or later (npm install -g @anthropic-ai/claude-code@latest)
.claude/settings.json files for unexpected hooks definitions
.claude/settings.json
.claude/settings.json to .gitignore unless project-level hooks are intentionally shared
.claude/settings.json as an empty JSON object ({}) so the sandbox always protects it
settings.local.json for security-critical deny rules (always protected, never committed to Git)
~/.claude/ and project .claude/ directories
postinstall scripts that write to .claude/ paths
CVE-2026-25725 illustrates the fundamental tension in AI agent tooling: these systems must be powerful enough to perform real engineering work, yet contained enough to prevent the code they execute from escaping its boundaries. Claude Code's sandbox was well-engineered in many respects — namespace isolation, seccomp filters, network proxying — but a single conditional branch that skipped non-existent files created a gap wide enough to drive a complete sandbox escape through.
CVE-2026-25725 also highlights the difficulty of retrofitting security boundaries onto systems that were not designed with them from the start. The sandbox was added as a containment layer after the tool was already in wide use — and the gap between what it promised and what it delivered was exploitable from day one.
The broader context — 14 sibling CVEs, 58+ documented file access failures, catastrophic data losses, and an architectural gap where 5 out of 6 tool types bypass the sandbox entirely — suggests that the industry's approach to AI agent containment is still in its early stages. As AI coding assistants gain deeper access to developer machines and production systems, the security boundary between the agent and the host becomes the highest-value attack surface in the entire stack.
All Claude Code users should verify they are running v2.1.2 or later. Audit all project-level .claude/settings.json files for unauthorized hook definitions. Monitor for unexpected file creation in .claude/ directories. Consider pre-creating settings.json as an empty object to ensure consistent sandbox protection.