C Claude Code Internals
| EN | ES

Bash Security

Bash 安全系统采用 5 层独立的深度防御。即使一层被绕过,其他层仍继续阻止攻击 — 从注入验证器和路径约束到沙箱隔离和环境清理。

5 防御层 22+ 安全验证器 12 设计原则 3 沙箱平台
! 深度防御 — 不是单一检查
每层独立运行。验证器层捕获注入,权限层执行允许/拒绝规则, 路径层防止遍历,文件系统层阻止受保护文件,沙箱限制 OS 级别 表面。所有 5 层在每个命令上运行。

架构 — 5 层

1
安全验证器 — 22+ 检查:注入、元字符、误解析攻击
2
权限系统 — 允许/拒绝规则、只读检测、前缀匹配
3
路径验证 — 每命令路径提取、遍历防止
4
文件系统权限 — 受保护文件/目录、符号链接解析、大小写规范化
5
沙箱 — seatbelt (macOS) / bubblewrap (Linux),文件系统 + 网络限制

命令执行管道

1. 模型发出 tool_use: Bash({ command: "..." })
2. checkPermissions() → bashToolHasPermission()(第 1–4 层)
3. 如允许 → call() → runShellCommand() → exec()
4. exec() 解析 shell 提供者($SHELL: zsh / bash / sh)
5. 可选:用 SandboxManager.wrapWithSandbox() 包装
6. spawn() 子进程(detached: true,自定义 env)
7. 基于文件的输出:O_APPEND(原子)+ O_NOFOLLOW(符号链接保护)
8. 捕获 stdout/stderr,应用截断,返回结果

注入的环境变量

SHELLShell 二进制路径
GIT_EDITOR'true' — 阻止交互式 git 编辑器
CLAUDECODE'1' — 通知 CLI 它们在 Claude Code 内
CLAUDE_CODE_SESSION_ID会话 ID(仅内部用户)

超时系统

进度报告在 2,000ms 后开始
自动后台预算:15,000ms
sleepDISALLOWED_AUTO_BACKGROUND_COMMANDS 中 — 从不自动后台

Security Validators (22+)

Early validators (short-circuit on allow)

# Validator What it catches
1validateEmpty空命令 → 允许
2validateIncompleteCommands以制表符、标志、运算符开头的片段
3validateSafeCommandSubstitution安全的 heredoc-in-substitution 模式
4validateGitCommit带简单引号消息的 git commit

Main validators — misparsing attacks

# Validator What it catches
5validateJqCommandsystem()-f/--from-file
6validateObfuscatedFlags标志名称中的引号字符
7validateShellMetacharacters参数中的 ;|&
8validateDangerousVariables重定向/管道上下文中的变量
9validateCommentQuoteDesync导致引号跟踪脱节的 #
10validateQuotedNewline引号内分隔命令的换行符
11validateCarriageReturnCR shell-quote / bash 分词差异
12validateNewlines分隔命令的换行符(非误解析)
13validateIFSInjection$IFS 变量使用
14validateProcEnvironAccess/proc/*/environ 访问
15validateDangerousPatterns反引号、$()$${}$[]、Zsh 展开
16validateRedirections输入 < 和输出 > 重定向(非误解析)
17validateBackslashEscapedWhitespace反斜杠空格绕过
18validateBackslashEscapedOperators\;\|
19validateUnicodeWhitespace非 ASCII 空白字符
20validateMidWordHash引号附近的 #
21validateBraceExpansion花括号展开模式 {a,b}
22validateZshDangerousCommandszmodloademulatesysopen 等(20 个命令)
23validateMalformedTokenInjection不平衡分隔符 + 分隔符(HackerOne eval 绕过)

Misparsing vs non-misparsing

Misparsing validators

Their ask results set isBashSecurityCheckForMisparsing: true, causing early blocking in the permission flow. Catch attacks that exploit differences between how the security parser and actual bash tokenize commands.

Non-misparsing validators

validateNewlines and validateRedirections — results are deferred to ensure misparsing validators still run first.

Quote extraction — 3 views

View What it does
withDoubleQuotes移除单引号,保留双引号
fullyUnquoted移除所有引号内容
unquotedKeepQuoteChars移除内容但保留引号分隔符

Safe redirection stripping

stripSafeRedirections() removes known-safe patterns:

2>&1 (stderr to stdout)
>/dev/null or 2>/dev/null
</dev/null (empty stdin)

Each pattern requires trailing boundary (?=\s|$) to prevent prefix attacks (e.g., >/dev/nullo would write to file nullo).

Permission Flow & Read-Only Commands

bashToolHasPermission() — 8-step pipeline

1.
checkPermissionMode() — acceptEdits → auto-allow mkdir, touch, rm, etc.
2.
checkReadOnlyConstraints() — Parse command → if proven read-only → allow
3.
bashCommandIsSafeAsync() — Run all 22+ validators → any "ask" → block with reason
4.
checkPathConstraints() — Extract paths → validate within allowed directories
5.
checkSedConstraints() — Special handling for sed -i in-place edits
6.
Permission rule matching — Check allow rules (prefix), check deny rules
7.
Sandbox auto-allow — If sandboxed + autoAllowBashIfSandboxed → allow
8.
ML Classifier (feature-gated) — ANT-only: bash classifier model → allow/deny

Compound command handling

Commands with &&, ||, ;, | are split via splitCommand_DEPRECATED(). Cap of 50 subcommands prevents CPU exhaustion. If any subcommand fails → entire command blocked.

Read-only command allowlist

File operations: ls, cat, head, tail, wc, file, stat, du, df, find, tree, realpath, md5sum, sha256sum, xxd
Text processing: grep, rg, awk, sed (no -i), sort, uniq, cut, tr, diff, comm, jq, yq, xq, column
Git (read): git status, git log, git diff, git show, git branch, git tag, git blame, git shortlog
Development: node -e, python -c, tsc --noEmit, eslint, prettier --check, cargo check, go vet
System: echo, printf, date, env, which, type, uname, hostname, whoami, id, pwd, test

Per-command flag validation

fd -x / -X — excluded: --exec / --exec-batch trigger code execution
fd -l — excluded: internally executes ls subprocess (PATH hijacking risk)
jq — blocks system(), -f, --from-file
sed -i — in-place edit: NOT read-only, requires explicit permission

Path Validation & Filesystem Protection

Per-command path extractors (30+ commands)

Commands Path extraction strategy
cd, ls, cat, head, tail标志剥离后的位置参数
rm, rmdir, mkdir, touch所有非标志参数
mv, cp源和目标参数
find第一个参数(搜索根)
grep, rg模式后的文件参数
sed-i 目标文件
git子命令特定提取
jq输入文件参数

POSIX -- end-of-options handling

filterOutFlags() correctly handles --: after it, ALL arguments are treated as paths, preventing:

rm -- -/../.claude/settings.local.json
# "-/../.claude/..." is a PATH, caught as traversal

Protected files & directories

Protected files (auto-edit blocked)

.gitconfig, .gitmodules, .bashrc, .bash_profile, .zshrc, .zprofile, .profile, .ripgreprc, .mcp.json, .claude.json

Protected directories

.git, .vscode, .idea, .claude

Claude config (extra protection)

.claude/settings.json, .claude/settings.local.json, .claude/commands/, .claude/agents/, .claude/skills/

Path safety checks

Check What it catches
NTFS ADS位置 2 之后的 :(备用数据流)
8.3 短名称~\d 模式(Windows 短文件名)
长路径前缀\\?\\\.\(Windows 扩展)
DOS 设备名CONPRNAUXNUL
三点路径组件中的 ...
符号链接解析原始路径和解析目标都检查
大小写规范化normalizeCaseForComparison() 全部小写

Sandbox & Environment Security

Sandbox platforms

Platform Technology Status
macOSseatbelt (sandbox-exec)内置
Linuxbubblewrap (bwrap)需要安装
WSL2bubblewrap需要安装
Windows 原生不支持

Sandbox decision flow

1. Sandboxing enabled? → No → no sandbox
2. dangerouslyDisableSandbox: true + areUnsandboxedCommandsAllowed() → no sandbox
3. Command in excludedCommands list? → no sandbox
4. Apply SandboxManager.wrapWithSandbox()

excludedCommands is NOT a security boundary — permission system still applies.

Bare git repo defense

Sandbox blocks writes to git-structural files at CWD: HEAD, objects/, refs/, hooks/, config. Post-command, scrubBareGitRepoFiles() deletes any planted files. Prevents attackers from planting malicious git hooks.

Subprocess env scrubbing

Activated when CLAUDE_CODE_SUBPROCESS_ENV_SCRUB is set (GitHub Actions context):

Category Variables stripped
AnthropicANTHROPIC_API_KEY, CLAUDE_CODE_OAUTH_TOKEN, ANTHROPIC_AUTH_TOKEN
AWSAWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN, AWS_BEARER_TOKEN_BEDROCK
GCP/AzureGCP/Azure 凭证变量
GitHub ActionsACTIONS_ID_TOKEN_REQUEST_TOKEN, 运行时令牌
OTEL可能包含认证令牌的头
INPUT_*上述所有 INPUT_ 前缀变体

Variables NEVER safe to strip

Category Variables Risk
执行PATH, LD_PRELOAD, LD_LIBRARY_PATH, DYLD_*二进制/库劫持
模块加载PYTHONPATH, NODE_PATH, CLASSPATH, RUBYLIB通过导入注入代码
代码执行GOFLAGS, RUSTFLAGS, NODE_OPTIONS通过标志执行任意代码
系统HOME, TMPDIR, SHELL, BASH_ENV行为修改

Dangerous Patterns, PowerShell & Destructive Warnings

Dangerous command patterns

Cross-platform (code execution)

python, python3, node, deno, tsx, ruby, perl, php, lua, npx, bunx, npm run, yarn run, bash, sh, ssh

Unix additions

zsh, fish, eval, exec, env, xargs, sudo

Zsh-specific (20 builtins)

zmodload, emulate, sysopen, syswrite, ztcp, zsocket, zf_rm, zf_mkdir, zf_rmdir, zf_ln, zf_mv, zf_chmod…

Destructive command warnings

Git: git reset --hard, git push --force, git clean -f, git checkout ., git stash drop/clear, git branch -D, git commit --amend
Filesystem: rm -rf, rm -r, rm -f
Database: DROP TABLE/DATABASE, TRUNCATE TABLE, DELETE FROM
Infrastructure: kubectl delete, terraform destroy

These are informational warnings in the permission dialog — not security blocks.

PowerShell security (parallel system)

Mirrors the Bash system with platform-specific adaptations: per-cmdlet CmdletPathConfig, case-insensitive matching, GIT_SAFETY_WRITE_CMDLETS, archive extractor detection.

PowerShell dangerous patterns

pwsh, powershell, cmd, wsl, iex, invoke-expression, start-process, saps, start-job, sajb, register-objectevent

PowerShell auto-mode block categories (4)

1
Download-and-Execute: iex (iwr ...) — equivalent to curl | bash
2
Irreversible Destruction: Remove-Item -Recurse -Force — equivalent to rm -rf
3
Persistence: Modifying $PROFILE, Register-ScheduledTask, registry Run keys
4
Elevation: Start-Process -Verb RunAs, -ExecutionPolicy Bypass, disable AMSI/Defender

12 Security Design Principles

1. Defense in Depth

Multiple independent layers each block attacks. Bypassing one layer doesn't compromise the others.

2. Fail-Safe Defaults

Unknown parameters, parse failures, complex commands → ask. The system never assumes safety.

3. Misparsing Awareness

Validators explicitly account for differences between security parser and actual bash tokenization.

4. Case-Insensitive Paths

normalizeCaseForComparison() applied everywhere to prevent macOS/Windows case-based bypasses.

5. Symlink Resolution

Both original path AND resolved target checked for all security decisions.

6. No Trust in User Controls

excludedCommands is explicitly NOT a security boundary — security comes from the permission system.

7. Subprocess Env Scrubbing

API keys and CI tokens stripped from subprocess envs in GitHub Actions contexts.

8. Bare Git Repo Defense

Sandbox blocks writes to git-structural files. Post-command scrubbing removes any planted files.

9. Per-Process Nonces

Bundled skills root uses randomBytes(16) to prevent pre-creation attacks on shared /tmp.

10. Compound Command Splitting

&&, ||, ;, | operators parsed — each subcommand validated independently. Cap of 50 prevents CPU exhaustion.

11. Quote Context Tracking

3 views of each command enable precise detection of metacharacters hidden in quoted contexts.

12. Boundary Assertions

Safe redirection stripping requires trailing boundaries (?=\s|$) to prevent prefix attacks.

i Output handling
Tool results > 30,000 chars are persisted to file; > 64 MB is the maximum persisted size. The EndTruncatingAccumulator keeps the beginning and end of output, truncating the middle with [... truncated ...]. Large outputs get a preview with a pointer to the full file for the Read tool.