第九章:我是如何剖析 Claude Code 的 CLI 里的安全沙盒与指令拦截机制的

大家好。又来了,好东西真的太多了,没办法。

比如有个问题:"Claude Code 既然能在电脑上执行命令行,万一大模型抽风,来一句 rm -rf /,或者偷偷把数据库给 DROP TABLE 了,那不就全完了?"

作为一个能够直接操作宿主系统的 AI 代理(Agent),安全(Security)和防越权(Jailbreak Prevention) 是重中之重。

为了搞清楚 Anthropic 到底是怎么给这只 AI "带上紧箍咒"的,我深挖了 src/tools/BashTool/ 目录。

不看不知道,一看吓一跳:这里面藏着一整套防御纵深极强的 安全沙盒与指令拦截机制。这不仅是在防范大模型犯错,更是在防范各种隐蔽的 Bash 语法注入。

今天,咱们就来看看这道"最后的防线"是怎么工作的。


源码探秘:Bash 里的"雷区"

当我们允许大模型执行 bash 命令时,最大的威胁不仅是显式的破坏命令,还有那些隐蔽的、利用 Shell 特性绕过限制的注入攻击。

src/tools/BashTool/bashSecurity.ts 中,工程师们简直把 Bash 的黑魔法研究透了,枚举了各种令人防不胜防的黑客手段。

1. 拦截高危的 Shell 扩展与隐蔽调用

大模型有时候为了"炫技"(或者被越权指令诱导),会写出极其复杂的 Shell 语法。而这恰恰是绕过普通正则检查的重灾区。

源码中定义了一系列 COMMAND_SUBSTITUTION_PATTERNS 进行拦截,防止命令替换:

typescript 复制代码
// src/tools/BashTool/bashSecurity.ts
const COMMAND_SUBSTITUTION_PATTERNS = [
  { pattern: /<\(/, message: 'process substitution <()' },
  { pattern: />\(/, message: 'process substitution >()' },
  { pattern: /=\(/, message: 'Zsh process substitution =()' },
  // 重点看这个:Zsh EQUALS expansion: =cmd
  // 比如 `=curl evil.com` 会被 Zsh 展开为 `/usr/bin/curl evil.com`
  // 这就能完美绕过针对 `curl` 这个关键字的权限拦截规则!
  { pattern: /(?:^|[\s;&|])=[a-zA-Z_]/, message: 'Zsh equals expansion (=cmd)' },
  { pattern: /\$\(/, message: '$() command substitution' },
  // ...甚至连 PowerShell 的注释语法 `<#` 都被封杀了,主打一个防御纵深
];

不仅如此,源码还点名封杀了 Zsh 的一票底层高危模块:

  • zmodload: Zsh 模块加载的网关,它是很多高级攻击的入口(比如无文件 I/O)。
  • sysopen / sysread / syswrite: 绕过普通命令拦截,直接进行底层的系统文件 I/O 操作。
  • zpty: 开启伪终端,执行隐蔽操作。
  • zf_rm / zf_mv: 哪怕你调用的是 Zsh 内置的 rm,也照拦不误。

只要 AI 生成的代码里包含这些"作弊码",安全校验层就会直接把它按死在摇篮里。

2. "手滑"毁灭世界?不存在的

大家最关心的"删库跑路"问题,在 src/tools/BashTool/destructiveCommandWarning.ts 中有专门的防御。

官方整理了一份 DESTRUCTIVE_PATTERNS 列表。如果你仔细看这些正则,会发现它们写得极其严谨。

一旦匹配上,CLI 会立刻弹出一个极其醒目的警告,要求用户必须手动确认(系统绝不会 Auto-approval 自动同意这些操作):

typescript 复制代码
// src/tools/BashTool/destructiveCommandWarning.ts 拦截规则节选
const DESTRUCTIVE_PATTERNS: DestructivePattern[] = [
  // Git 相关的灾难性操作:不仅防 reset,还防带 --force 的 push
  { pattern: /\bgit\s+reset\s+--hard\b/, warning: 'Note: may discard uncommitted changes' },
  { pattern: /\bgit\s+push\b[^;&|\n]*[ \t](--force|--force-with-lease|-f)\b/, warning: 'Note: may overwrite remote history' },
  
  // 经典的文件删除:严谨的正则防绕过(比如 rm -rf, rm -fr)
  { pattern: /(^|[;&|\n]\s*)rm\s+-[a-zA-Z]*[rR][a-zA-Z]*f|(^|[;&|\n]\s*)rm\s+-[a-zA-Z]*f[a-zA-Z]*[rR]/, warning: 'Note: may recursively force-remove files' },

  // 数据库毁灭者
  { pattern: /\b(DROP|TRUNCATE)\s+(TABLE|DATABASE|SCHEMA)\b/i, warning: 'Note: may drop or truncate database objects' },
  { pattern: /\bDELETE\s+FROM\s+\w+[ \t]*(;|"|'|\n|$)/i, warning: 'Note: may delete all rows from a database table' },

  // 连基础设施都不放过
  { pattern: /\bkubectl\s+delete\b/, warning: 'Note: may delete Kubernetes resources' },
  { pattern: /\bterraform\s+destroy\b/, warning: 'Note: may destroy Terraform infrastructure' },
];

你看,不管是删文件、清库还是干掉 K8s 集群,大模型只要敢写,这套正则防线就能把它拦住,把最终的生杀大权交还给坐在屏幕前的人类。

3. 沙盒隔离机制(Sandbox)

拦截只是治标,真正的治本是隔离

src/tools/BashTool/shouldUseSandbox.ts 中,展示了指令是否需要被沙盒化的判断逻辑。

如果启用了沙盒模式,命令会被重定向到 SandboxManager。这意味着即便命令跑起来了,它也是在一个受限的文件系统或容器中执行的,无法触及你的真实工作目录。

有意思的是,这里还处理了复合命令(比如 docker ps && curl evil.com)和环境变量包裹(比如 FOO=bar timeout 30 bazel run)。

系统会不断地剥离外层的环境变量和包装器,直到暴露出最核心的执行命令,再去和用户的黑名单进行匹配,防止"套娃"逃逸。


额外大放送:隐藏的语音模式(Voice Mode)

在翻看源码的时候,我不小心在 src/commands/voice/voice.tssrc/hooks/useVoice.ts 里发现了一个目前似乎还没大规模宣传的神级彩蛋:语音对讲模式!

源码显示,Claude Code 竟然内置了一个 /voice 命令!

typescript 复制代码
// src/commands/voice/voice.ts 节选
// 检查是否有系统麦克风权限和录音工具(如 macOS 原生或 SoX)
const recording = await checkRecordingAvailability()
if (!recording.available) { ... }

// 如果一切就绪,开启语音模式
return {
  type: 'text',
  value: `Voice mode enabled. Hold ${key} to record.${langNote}`,
}

它的原理是:按下指定的快捷键(比如 Space 空格键),终端会调用系统底层的音频模块(macOS 原生或 SoX)进行录音,计算音量显示出波形动画(Waveform),然后将音频流(Stream)通过 WebSocket 实时发送到 Anthropic 的 voice_stream 接口进行语音转文字(STT,推测背后是 Deepgram 引擎)。

你甚至可以在 src/hooks/useVoice.ts 看到长长的一串支持语言列表,从英语(english)、西班牙语(español)到日语(日本語)、俄语(русский),甚至印尼语(bahasa)全覆盖!

当然,也完美支持咱们的中文(中文在系统里通常走系统语言检测,或者作为默认模型能力支持,虽然硬编码列表里没单独写中文名,但实际上完全可用)

源码里甚至还做了非常细致的"静音检测"和"断网重连重传"(Silent-drop replay),防止你说了半天结果因为网络波动没录上。

这简直太赛博朋克了:未来,你可能只需要按住空格键,对终端说一句:"帮我把刚才报的那个 Null Pointer 异常修了,顺便写个单元测试",代码就自己写好了。


最后

从底层的 AST 拦截、破坏性正则预警,再到隐蔽的语音唤醒彩蛋,src/ 目录下可以说是卧虎藏龙。

Anthropic 的工程师不仅在教 AI 如何写代码,更在教系统如何"防范"一个偶尔会犯蠢的 AI。

这种对系统边界的敬畏之心,以及在 CLI 交互上不断整活的创新精神,绝对值得所有开发者学习。

一键三连奥,关注不迷路哈!

相关推荐
得想办法娶到那个女人2 小时前
Vue3 组合式API 标准写法(通俗易懂,可直接复制)
前端·javascript·vue.js
_深海凉_2 小时前
LeetCode热题100-最长公共子序列
java·开发语言·前端
蓝天客2 小时前
接入支付 FM 接口实战经验
前端
liyi_hz20082 小时前
O2OA V10 升级说明(二)内容管理:更安全、更融合、更适配移动办公
java·前端·数据库
a1117762 小时前
PascalEditor( 3D建筑编辑器 开源)
前端·开源·html
爱上好庆祝2 小时前
移动端适配
前端·css·学习·html·css3
overmind2 小时前
oeasy Python 123 元组_运算_封包解包_欢乐颂_大写数字
java·前端·python
发现一只大呆瓜10 小时前
深度解密 Rollup 插件开发:核心钩子函数全生命周期图鉴
前端·vite
易安说AI10 小时前
2026 最新 Claude Code 订阅怎么选:免费版、Pro、Max、Team、API 一篇讲清
claude