Bash Security Pipeline

The shell command security system in claude-code, implemented in bashSecurity.ts (2,308 lines). Runs 25+ validators in a specific chain to evaluate every shell command before execution.

The Validator Chain

Validators run sequentially at bashSecurity.ts:2308-2378. Three structural vulnerabilities are documented in the source itself:

1. Early-Allow Short-Circuits

validateGitCommit and validateSafeCommandSubstitution can return allow, which bypasses all subsequent validators. The source contains its own warning:

"validateGitCommit returns allow -> bashCommandIsSafe short-circuits -> validateRedirections NEVER runs -> ~/.bashrc overwritten"

2. Three-Parser Differentials

Commands are parsed by three different parsers with different edge-case behavior:

Parser Used For
splitCommand_DEPRECATED Legacy command splitting
tryParseShellCommand Modern parsing
ParsedCommand.parse Structured parsing

A known differential: "shell-quote's [^\s] treats CR as a word separator (JS \s ⊃ \r), but bash IFS does NOT include CR." Attackers can exploit differences between what the validator thinks a command does and what bash actually executes.

3. Non-Misparsing Result Discardal

validateRedirections catches a dangerous > redirect, but if no "misparsing" validator fired, the result lacks isBashSecurityCheckForMisparsing. The permission-pipeline discards the warning if the user has a matching allow rule. Result: echo "payload" > ~/.bashrc passes the entire chain if the user has Bash(echo:*) allowed.

The 50-Subcommand Cap (CVE)

const MAX_SAFE_CHECK_SUBCOMMANDS = 50
// 50 is a generous allowance for legitimate usage.
// After 50, fall back to ask-permission rather than deny.

Adversa AI's exploit: 49 true no-ops + malicious curl = 50 subcommands. The parser sees 51, exceeds the cap, and falls through from deny to ask-permission. In CI/CD or --dangerously-skip-permissions mode, no human sees the prompt.

The assumption was correct for human-authored commands. It didn't account for AI-generated command sequences from prompt injection — where a malicious CLAUDE.md instructs the AI to generate a 50+ subcommand pipeline that looks like a legitimate build process.

Patched silently in v2.1.90. The tree-sitter AST parser (already in bashSecurity.ts) could have fixed this with a one-line change: deny-on-overflow instead of ask-on-overflow.

The CVE Cluster

CVE CVSS Mechanism Fixed
CVE-2025-59536 8.7 Pre-trust hook execution — RCE before trust dialog v1.0.111
CVE-2026-21852 5.3 ANTHROPIC_BASE_URL redirect exfiltrates API key v2.0.65
CVE-2025-54795 8.7 Confirmation prompt bypass via prompt crafting v1.0.20
Adversa deny-cap bypass TBD 50-subcommand overflow v2.1.90
CVE-2026-35020/21/22 TBD Command injection in which.ts, promptEditor.ts, auth.ts Unpatched

Common root cause: the safety enforcement boundary is inside the model's reasoning layer, not below it.

Key Claims

Sources