Claude Code 这类命令行 AI 编程助手,正在把开发者的工作方式从“写代码”变成“指挥 Agent 写代码”。你给它一个自然语言任务,它自己读仓库、改文件、跑测试、执行命令。听起来很美,但安全研究员最近披露的攻击结论值得所有使用者重视:当自动模式开启时,针对 Claude Code 的高成功率攻击并不是“诱导模型输出有毒文本”,而是让 Agent 在无人确认的情况下,把项目文件、依赖描述、文档注释里的隐藏指令当成正常任务去执行。
这个问题的本质,和传统 Web 安全很不一样。传统攻击考虑的是“输入是否可信”,Agent 场景要考虑的是“仓库里每一个字符都可能变成指令”。如果你正在用 Claude Code,或者正打算在团队里引入 AI 编程助手,这篇文章值得读完。我会先讲清楚攻击面为什么存在,再拆解研究者披露的攻击链路,最后给出一套可以直接落到工作流里的权限收敛、审计 hook 和排查方案。
1. 这篇文章真正要解决的问题
先说结论:Claude Code 自动模式的最大风险,不是模型会“失控”,而是它把“操作确认”这个安全闸门交给了一个可以被间接指令操纵的决策者。
在默认的交互模式下,Claude Code 执行敏感操作前会请求用户确认,开发者还能看到它准备跑什么命令。但自动模式下,这个确认环节被大幅压缩,Agent 可以按自己的计划连续执行多个工具调用。一旦攻击者能往 Agent 读取的内容里植入恶意指令,自动模式就会把这些指令当成项目任务的一部分执行。
这里面最隐蔽的一点是:攻击者不需要攻破你的电脑,也不需要拿到你的 API Key。他只需要让你把某个仓库 clone 下来、跑一下测试、或者安装一个依赖。只要 Agent 读取了包含恶意指令的文件,那么从“读取文件”到“执行命令”这条链路就变成了攻击通道。
如果你属于下面任一类读者,这篇文章尤其有用:
- 正在个人项目里使用 Claude Code,想让自动任务更安全;
- 团队计划引入 Agent 编程工具,需要提前评估供应链风险;
- 负责公司 AI 工具落地,需要给“自动执行”划定边界;
- 对 AI Agent 安全方向感兴趣,想理解“提示注入 + 工具调用”如何组合成真实攻击链。
这篇文章会给出攻击面分析、攻击链拆解,以及可落地的权限配置、审计脚本和排查思路。我不会给出可复现的攻击载荷,但会从防御方视角把原理讲透。
2. 基础概念与核心原理
先把几个关键概念对齐。这些术语后面会反复出现。
2.1 Claude Code 是什么
Claude Code 是 Anthropic 推出的终端 AI 编程助手。它能读取项目文件、跨文件搜索、编辑代码、运行测试和执行 shell 命令。开发者通过自然语言下达任务,它通过“工具调用”完成操作。模型本身不直接执行命令,而是输出一个结构化的工具调用,由 Claude Code 宿主机解析并执行。这个“模型决策、宿主执行”的模式,是理解安全问题的关键。
2.2 自动模式
自动模式是 Claude Code 为提高任务连续性而提供的能力。开启后,模型可以在权限允许的范围内自主执行多个步骤,不需要每一步都停下来等待用户确认。它解决的问题很明确:长任务场景下如果每跑一条命令都要确认,Agent 的实用性会大打折扣。
但自动模式改变了一个基本安全假设:默认模式下,人是最终裁判;自动模式下,模型在大部分环节里既是执行者,又是裁判。如果攻击者能影响模型的判断,那么“自动化执行”就变成“自动化利用”。
2.3 Opus 5 与“自动模式攻击”的关系
标题里提到的 Opus 5,可以理解为 Claude 模型系列的最新代际代号。从安全角度看,我建议不要把这次攻击理解成“某个模型版本私有的漏洞”。更稳妥的判断是:模型推理能力越强,自动模式能完成的操作越复杂,攻击面也随之扩大。Opus 5 这类高性能模型被攻击者盯上,不是因为模型“更笨”,恰恰是因为它能完成更复杂的工具链操作,植入恶意指令的收益变得更高。
2.4 提示注入
提示注入是 Agent 安全的核心问题之一。传统提示注入发生在“用户输入”和“系统指令”之间,攻击目标是让模型忽略约束。Agent 场景里更常见的是间接提示注入:攻击者把恶意指令放在模型会读取的文档、依赖描述、终端输出、甚至日志文件里,让模型在正常完成任务时“顺便”执行攻击者要求。
为什么这是结构性难题?因为 Agent 的天职就是处理不可信内容。一个开发助手必须读 README、必须看业务代码、必须理解第三方依赖,而这些东西都可能包含攻击者控制的文本。模型没有办法天然区分“这是项目说明”和“这是对我的命令”。
2.5 工具调用与权限边界
工具调用是 Claude Code 执行动作的接口。常见的工具包括读文件、编辑文件、运行 Bash 命令、执行 MCP 工具。安全设计上,每个工具调用都应该经过权限校验:这个操作是否允许、这个路径是否越界、这条命令是否在白名单里。
自动模式攻击的核心,就是绕过或滥用这道校验。研究者披露的高成功率,本质上不是因为某个权限校验被暴力绕过,而是攻击者利用的是“模型认为该命令很正常”这个心理环节。一旦模型把恶意命令当成项目必要的测试命令,它自己就会在权限范围内发起执行。
可以做一个类比:自动模式就像一个手持 sudo 权限、同时被要求阅读所有陌生邮件的实习生。邮件里写着“按附件清单执行清点”,他照做了,最后发现附件清单是攻击者写的。邮件的不可信他能理解,但他无法理解“清单里的语法为什么不是指令”。
3. 攻击面梳理:自动模式下哪些入口可能被利用
要防御自动模式攻击,第一步是梳理攻击入口。从公开研究披露和 Agent 工具的设计来看,主要入口集中在六个方向。
3.1 项目内文档与内存文件
Claude Code 会读取项目里的 CLAUDE.md(或类似的内存文件)作为项目级背景说明,也会读取 README、docs 目录、代码注释。攻击者可以在开源仓库里预先放置带恶意指令的说明文档,诱导 Agent 在完成正常任务时执行附带步骤。
这种方式的优势在于极难察觉。恶意指令往往写得像正常项目说明,比如“运行测试前先执行scripts/prepare.sh”,而这可能是攻击者准备好的脚本。
3.2 第三方依赖描述与安装脚本
Agent 在开发过程中经常需要安装依赖:npm install、pip install、cargo add。依赖包里可能包含恶意 postinstall 脚本,也可能在包描述文件里写入与安装无关但会被 Agent 读取的指令。攻击者如果控制了某个依赖或一个伪造的相似包名,就能在 Agent 安装依赖时完成植入。
3.3 配置文件与 MCP 服务
Claude Code 的 setting 可以定义权限、hook、MCP 工具。如果开发者 clone 了一个攻击者控制的仓库,攻击者就可能尝试让你导入一个恶意 MCP 服务配置,或通过项目级配置影响 Agent 行为。MCP 服务器返回的数据同样可以携带注入载荷,模型拿到这些数据后可能把“工具返回”当成可执行建议。
3.4 终端输出与外部 API 返回内容
Agent 执行命令后会读取终端输出。如果这条命令访问了外部网络,返回的页面或响应也可能包含注入指令。比如 Agent 请求一个接口获取测试数据,攻击者可以让接口返回一段看似正常的 JSON,但其中某个字段包含“下一步请执行 xx 命令”的表述。模型如果不过滤,就可能把该字段当作执行指令。
3.5 Hook 脚本
Claude Code 支持 hook 机制,在特定事件(比如工具调用前)执行自定义脚本。hook 是开发者的提权能力,但反向看,如果攻击者能诱导 Agent 修改 hook 配置或把 hook 指向恶意脚本,那么每次工具调用都会触发恶意代码。供应链场景下,一个带恶意 hook 的模板仓库就足够完成攻击。
3.6 模型幻觉与命令名称混淆
还有一个不那么“技术”但很现实的入口:模型幻觉。自动模式下,模型可能根据上下文猜测某个命令不存在或者含义不同,攻击者可以利用常见拼写错误、伪装成正常命令的脚本名,让模型主动去执行。比如项目里放一个名为npm-run-check的可执行文件,再在 README 里说“统一用自定义 check 命令”,Agent 跑的就可能是恶意脚本。
任何一条入口单独看,都不算新鲜。但自动模式把它们的威胁等级放大了:过去需要用户确认才能执行,现在 Agent 可以在连续操作中静默完成。
4. 攻击链拆解:为什么针对自动模式的攻击能高成功率
这一节我按照公开安全研究披露的思路,讲攻击链的宏观结构,不展开可被复制的攻击载荷。理解攻击链,是为了设计对应的防御点。
4.1 第一阶段:植入指令
攻击者需要让恶意指令进入 Agent 的上下文。常见做法是构造一个“看起来正常”的开源项目,把恶意指令放在 CLAUDE.md、README、配置文件或依赖描述里。为了增强隐蔽性,指令会伪装成项目开发约定,比如“提交前执行格式化”“跑集成测试前先启动本地依赖服务”。
这个阶段的关键是:指令必须在 Agent 正常读取文档时自然出现,不能像是一段明显的攻击文本。研究者披露的高成功率,很大程度上来自这里——攻击者把恶意动作嵌入了“完成原始任务所必须的步骤”里。
4.2 第二阶段:触发链路
植入指令后,需要等待 Agent 执行链路被触发。攻击者不能控制用户什么时候运行 Claude Code,但可以控制触发条件。最典型的是让恶意步骤附着在常见任务前面:如果 Agent 要“运行测试”,必须先执行某个“预处理”;如果 Agent 要“安装依赖”,必须执行某个“初始化”。
由于 Agent 的任务分解能力很强,它通常不会怀疑“先执行 prepare 脚本再测试”这种步骤不合理。在自动模式下,模型会连续执行多个工具调用,恶意步骤就混在其中,没有人工检查。
4.3 第三阶段:利用 Agent 的“有用性”
这是自动模式攻击真正危险的地方。Claude Code 的模型被训练成乐于助人,会尽力完成用户的原始任务。攻击者利用的正是这种“帮助倾向”:它不会因为某个步骤来源可疑就拒绝执行,反而会努力把可疑步骤解释成“合理的一部分”。
这就是为什么研究者在报告里强调,这次攻击的高成功率不是因为某个漏洞可以稳定绕过权限,而是因为整个 Agent 在自动模式下的行为模式天然偏向执行。人类在收到陌生邮件时会有怀疑,但模型面对“项目文件里写明要执行”的指令时,默认信任度非常高。
4.4 攻击成功后的影响面
攻击指令执行后,影响范围取决于 Agent 持有多少权限:
- 可以读写项目文件,篡改源代码、删除数据;
- 可以读取环境变量、密钥文件,导致凭据泄露;
- 可以安装恶意依赖,形成供应链污染;
- 可以调用 MCP 工具,访问企业内网服务;
- 可以执行 git 操作,把恶意代码提交到远程仓库。
研究者把这类攻击归类为“Agent 滥用”而非“模型越狱”,是有道理的。模型并没有被神秘力量控制,它只是在一个过于信任自动执行的设计框架里做出了“合情合理”的坏选择。
5. 防御边界与最小权限配置
接下来是可落地的防御。核心原则只有四个字:最小权限。不要给 Claude Code 一把万能钥匙,再寄希望于它每次都能识别坏钥匙。
5.1 用 settings.json 收紧权限
Claude Code 支持通过配置文件定义权限规则。实际项目中,我建议把 shell 类工具的使用范围尽量收窄,不要直接允许所有 Bash 命令。
以下是一个偏保守的 settings.json 示例。字段含义我会逐个解释,但你使用的版本是否完全支持这些字段,以官方文档为准。
// 文件路径:~/.claude/settings.json { "permissions": { "allow": [ "Read(**)", "Glob(**)", "Edit(**)", "Bash(git status)", "Bash(git diff)", "Bash(npm run lint)" ], "deny": [ "Bash(curl *)", "Bash(wget *)", "Bash(pip install *)", "Bash(npm install *)", "Bash(sudo *)", "Bash(chmod *)", "Write(**/.env)", "Write(**/credentials*)" ] } }这份配置的关键逻辑是:
- allow 里只放开发中高频且无害的读操作和安全命令,比如 git status、git diff、lint;
- deny 里把高危命令先全部挡掉。curl、wget、pip install、npm install 这类命令,在自动模式下风险很高,宁可每次手动执行,也不要让 Agent 静默安装;
- Write 规则对 .env、credentials 这类敏感文件做了保护,防止 Agent 覆盖关键配置。
如果团队项目里确实需要 Agent 安装依赖,建议把安装命令做成精确匹配,而不是放开整个工具:
{ "permissions": { "allow": [ "Bash(npm install --save-dev eslint)" ] } }这样 Agent 只能执行你明确允许的那一条命令组合。
5.2 用 deny 规则保护关键路径
如果你的项目里有密钥目录、部署目录、数据库脚本目录,应该显式拒绝 Agent 写入。不要让“配置文件在项目里,所以就归 Agent 管”成为一种默认假设。
{ "permissions": { "deny": [ "Write(/Users/me/.ssh/**)", "Write(/Users/me/.aws/**)", "Write(./deploy/**)", "Write(./secrets/**)" ] } }注意,deny 规则只能在配置层面限制 Claude Code,如果攻击者已经通过恶意依赖拿到 shell,配置文件挡不住。所以权限配置要和下面要讲的环境隔离配合使用。
5.3 在隔离环境中运行自动任务
对于不需要访问本地敏感文件的自动任务,强烈建议在 Docker 容器里运行 Claude Code 自动模式。容器天然提供了文件系统和网络隔离,即使 Agent 被诱导,也无法直接读取宿主机 SSH 密钥。
这里给出一个最小化的容器运行思路,不需要构建镜像:
# 创建一个只读挂载的项目目录容器 docker run --rm -it \ -v "$PWD:/app:ro" \ -v claude_home:/home/user/.claude \ -e ANTHROPIC_API_KEY="$ANTHROPIC_API_KEY" \ --network none \ node:20-slim \ bash说明:
-v "$PWD:/app:ro"把项目目录只读挂载,Agent 无法修改源码,就算恶意指令要求写文件也会失败;--network none断开网络,阻止 Agent 访问外部接口,也间接阻断攻击者借助命令外传数据;- 如果你需要让 Agent 安装依赖,可以考虑加代理或者使用内部镜像源,而不是直接放开网络。
当然,这种方式的代价是很多自动任务跑不了。所以更实际的思路是分层:个人开发环境打开完整权限,但保持人工确认;无人值守的批量任务走容器;涉及敏感凭据的任务永远不在自动模式下执行。
5.4 使用 audit hook 记录每次工具调用
Claude Code 的 hook 机制,可以在工具执行前触发自定义脚本。我们可以利用这个能力,在每次 Bash 命令执行前把命令写入审计日志,并对危险命令直接拦截。
下面是一个 Node.js 写的 preToolUse hook 示例。它做两件事:记录完整命令,检测危险模式并阻止执行。
// 文件路径:/path/to/audit-bash-hook.js const fs = require("fs"); const path = require("path"); const logPath = "/var/log/claude-code-audit.log"; // 从 HookInput 中读取本次工具调用信息 function readInput() { let body = ""; process.stdin.on("data", (chunk) => { body += chunk; }); process.stdin.on("end", () => { handle(JSON.parse(body)); }); } function handle(input) { const toolName = input.tool_name || "unknown"; const toolInput = input.tool_input || {}; const decision = input.decision || "unknown"; const logLine = JSON.stringify({ time: new Date().toISOString(), tool_name: toolName, command: toolInput.command || "", decision, }) + "\n"; fs.appendFileSync(logPath, logLine); const cmd = toolInput.command || ""; const dangerousPatterns = [ /(^|\s)(curl|wget)\s/i, /(^|\s)(nc|netcat)\s/i, /(^|\s)(sudo|su)\s/i, /(^|\s)(base64\s+-\s*d\s*)/i, /(^|\s)(rm\s+-\s*rf)\s/i, ]; for (const pattern of dangerousPatterns) { if (pattern.test(cmd)) { // 返回一个结构化结果,通知宿主阻止本次调用 console.log(JSON.stringify({ decision: "block", reason: "dangerous command matched by audit hook: " + cmd, })); return; } } // 默认放行,但已在日志中留下记录 console.log(JSON.stringify({ decision: "approve", reason: "all good", })); } readInput();在 settings.json 里注册这个 hook:
{ "hooks": { "PreToolUse": [ { "matcher": "Bash", "hooks": [ { "type": "command", "command": "node /path/to/audit-bash-hook.js" } ] } ] } }这段代码的重点是:
- 日志里记录了每一个被 Bash 工具执行的命令。即使你暂时不想拦截,也应该先保留完整的审计痕迹;
- 危险命令检测规则可以根据团队规范调整,优先覆盖 curl、wget、sudo、加密命令、强制删除这几类;
- hook 如果返回 block,宿主会停止本次工具调用,这比“事后看日志”更能止损。
需要注意,hook 脚本本身要放在 Agent 无法修改的路径下,否则攻击者可能先让 Agent 改掉 hook 脚本再触发恶意命令。
5.5 不信任项目里的内存文件
现实中,很多人都习惯把 CLAUDE.md 作为团队规范写入仓库。这个做法在小型可信团队里没问题,但对从外部 clone 的项目,不要默认信任其中的“前置步骤”。
一个可行策略是:把项目内存文件分成两层。一层是团队维护的可信版本,入库前经过 review;另一类是第三方项目自带的记忆文件,Agent 读取时只作为背景参考,不应触发命令执行。如果工具配置允许,可以在读取第三方 CLAUDE.md 之前先人工检查一遍内容。
6. 完整示例:扫描注入指令与审计日志分析
除了配置层面的防御,你还需要定期检查项目里是否存在可疑指令。这一段给出两个可以直接使用的检查思路。
6.1 扫描项目文档中的可疑指令
这个 Python 脚本会遍历常见文档文件,查找指向“执行命令”的文本模式。它不能分析语义,但能快速筛出高风险内容。
# 文件路径:scan_injection.py import os import re TARGET_EXTENSIONS = {".md", ".txt", ".rst", ".json"} SUSPICIOUS_PATTERNS = [ r"ignore\s+(the\s+)?(above|previous|prior|earlier)\s+(instructions|rules|commands)", r"do\s+not\s+(tell|notify|inform|warn)\s", r"execute\s+(the\s+)?(following|this|below)\s+(command|script)", r"run\s+(the\s+)?(following|this|below)\s+(command|script)", r"curl\s+.*\|\s*(bash|sh)", r"wget\s+.*\|\s*(bash|sh)", r"(base64\s*-\s*d\s*-\s*decode)", r"(eval|exec)\s*\(.*\)", ] def scan_file(filepath): try: with open(filepath, "r", encoding="utf-8", errors="ignore") as f: content = f.read() except Exception as e: print(f"[ERROR] {filepath}: {e}") return lines = content.splitlines() for idx, line in enumerate(lines, 1): for pattern in SUSPICIOUS_PATTERNS: if re.search(pattern, line, re.IGNORECASE): print(f"[SUSPECT] {filepath}:{idx}: {line.strip()[:120]}") def main(): root = os.getcwd() for dirpath, dirnames, filenames in os.walk(root): # 跳过常见依赖目录 skip = {"node_modules", ".git", "dist", "build", "venv", "__pycache__"} dirnames[:] = [d for d in dirnames if d not in skip] for name in filenames: ext = os.path.splitext(name)[1].lower() if ext in TARGET_EXTENSIONS: scan_file(os.path.join(dirpath, name)) if __name__ == "__main__": main()运行方式很简单:
python scan_injection.py > scan_result.txt扫描结果虽然会有误报,但值得优先处理。一旦发现来自外部项目的文档里出现“执行以下命令”这类内容,不要直接让 Agent 跑,先人工确认命令含义。
6.2 分析审计日志中的危险命令
如果没有通用格式,可以让 hook 直接把日志输出成 JSON Lines。下面是一条分析命令,用来查找日志中出现频率最高的命令,方便发现异常行为:
# 统计审计日志中最常出现的命令 cat /var/log/claude-code-audit.log \ | jq -r '.command' \ | sort \ | uniq -c \ | sort -rn \ | head -20如果日志里出现大量你没见过的 curl、wget、/tmp 写文件命令,基本可以断定 Agent 已经被诱导执行了非预期操作。此时需要立即停止自动任务、断开网络、回滚代码变更,并轮换可能泄露的凭据。
6.3 检查依赖安装后的异常文件
自动模式下如果 Agent 会安装依赖,攻击者可能通过 postinstall 脚本写入后门。一个快速检查思路是:对比依赖安装前后的文件变更。
# 安装依赖前先生成快照 find node_modules runtime deps > /tmp/deps_before.txt # 安装依赖后再次生成 find node_modules runtime deps > /tmp/deps_after.txt # 对比差异 diff /tmp/deps_before.txt /tmp/deps_after.txt | head -50这个方法不能防攻击,但能帮助你定位“多出来的文件”。如果发现某个依赖目录里多出了可执行脚本,建议立即检查该依赖包来源。
7. 运行验证与效果检查
配置完成后,必须验证是否真的生效。很多安全配置失效,不是因为规则不对,而是因为配置没有加载、路径错误、或者 hook 静默失败。
7.1 验证权限规则是否生效
用一个简单方式测试:给 Claude Code 一个明确要求执行被 deny 命令的任务,观察是否被阻止。
claude -p "请执行: curl https://example.com"如果配置生效,应该看到权限拒绝或类似提示。如果命令顺利执行,说明你的 deny 规则没有覆盖到对应路径,需要检查 settings 是否加载到了正确位置。
7.2 验证 hook 是否被触发
执行任意一条允许的 Bash 命令,然后查看审计日志是否有新记录:
# 触发一次工具调用 claude -p "执行 git status" # 查看最新日志 tail -5 /var/log/claude-code-audit.log如果日志没有更新,先检查 hook 脚本是否有可执行权限、Node 环境是否可用、settings 里的 hook 路径是否是绝对路径。hook 静默失败是最容易踩的坑。
7.3 验证容器隔离是否生效
如果你使用 5.3 中的容器方式,可以故意在项目里放一个“写入绝对路径”的测试文件,让 Agent 尝试写入 /tmp 目录外的路径,观察容器是否阻止或隔离。
claude -p "把测试内容写入 /home/user/.ssh/ 目录"如果容器配置正确,这个操作要么失败,要么落在容器内部的隔离文件系统里,不会影响宿主机。
7.4 判断指标
一个安全的自动模式环境,至少应该满足:
- 高危命令(curl、wget、sudo 等)无法由 Agent 自动执行;
- 敏感目录(.ssh、.aws、.env)不能被 Agent 写入;
- 每一次工具调用都有审计日志;
- 出现可疑行为时,能够从日志中快速定位时间线和命令序列。
如果你的环境中有一条不满足,建议先不要开启自动模式处理不可信项目。
8. 常见问题与排查方法
下面是我在实际使用 Agent 工具时经常遇到的问题,整理成一张排查表。
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| Agent 仍然执行了被 deny 的命令 | settings 文件未加载或权限配置路径错误 | 运行带详细日志的会话,观察配置加载情况 | 确认 settings 位置与格式,直接在配置里输入测试命令验证 |
| hook 一直没有生效 | hook 脚本缺少执行权限、Node 路径不对、matcher 不匹配 | 手动执行 hook 脚本,检查 stderr 输出 | 用绝对路径,先在小范围 matcher 上验证,再扩展到 Bash |
| Agent 读取第三方 CLAUDE.md 后执行了奇怪命令 | 项目文档被间接注入恶意指令 | 扫描文档中“执行”“必须”“忽略之前指令”等关键词 | 对第三方项目文档先人工 review,再让 Agent 继续任务 |
| MCP 工具返回了可疑格式内容 | MCP 服务返回内容中包含注入载荷 | 查看 MCP 服务器日志和返回数据 | 只启用可信 MCP 服务,限制工具调用范围,对返回值敏感字段做过滤 |
| 自动模式下 Agent 安装了一个恶意依赖 | 依赖安装命令未被 deny,供应链被污染 | 对比依赖目录快照,查看 lockfile 变更 | 收紧 allow 规则,依赖安装改为手动或独立阶段执行 |
| 审计日志没有记录命令内容 | hook 的 tool_input 字段名与版本不匹配 | 打印 hook 接收到的完整 JSON,确认字段 | 按实际版本调整字段解析逻辑 |
| 容器内 Agent 没网络但任务失败 | 任务本身依赖外部 API | 查看容器内网络策略和错误输出 | 通过内部代理放行必要域名,而不是关闭全部网络 |
遇到异常时,第一件事不是急着重跑任务,而是先保留现场:复制审计日志、记录当前 git 状态、截图工具调用序列。这样才能定位是配置问题、供应链问题,还是模型被诱导。
9. 最佳实践与工程建议
把安全配置做对,只是第一步。真正能在团队里长期落地,需要形成工程规范。
9.1 团队统一维护权限基线
不要每个人都各自维护一份 settings.json。建议把经过评审的权限基线放入团队仓库,同时允许个人在本地通过额外的 settings 文件补充业务需求。权限变更要走 review,尤其是放开 shell 命令白名单时,必须写清楚用途和失效时间。
9.2 自动模式只处理“低成本”任务
一个实用的分层原则是:自动模式只处理后果可控的任务,比如生成代码、写测试、重构局部逻辑。涉及安装依赖、修改部署配置、访问外部网络、操作密钥的任务,强制回到人工确认模式。
这个原则的落地方式,是把“是否允许自动执行”的决定交给任务类型,而不是留待现场判断。提前定义好哪些工具调用在自动模式下禁用,比依赖模型自己判断安全得多。
9.3 对第三方项目保持“不信任”默认
从外部 clone 项目时,先做一次注入扫描,再检查 CLAUDE.md、README、安装脚本和 lockfile diff。不要因为项目在 GitHub 上有很多 star 就默认可信,供应链攻击往往伪装在最流行的地方。
9.4 建立 Agent 操作审计基线
如果你的团队已经使用 Claude Code 完成日常任务,建议把审计日志接入集中式日志平台。这样既能在事后追溯,也能通过告警规则提前发现异常模式,比如短时间内出现大量 curl 命令、频繁写 /tmp、读取 .ssh 目录等。
9.5 发现攻击向研究员报告
如果你是安全研究方向的读者,遇到 Agent 工具的潜在漏洞,建议通过官方渠道提交报告,而不是公开披露攻击载荷细节。AI Agent 安全问题还很新,研究者和厂商之间的协作机制会直接影响整个生态的安全性。
10. 总结与后续学习方向
Claude Code 自动模式的高成功率攻击,给所有 Agent 工具使用者提了一个醒:当我们把“执行命令”的权限交给模型时,安全边界必须从“防外部输入”扩展到“防一切模型可读内容”。攻击者不一定要攻破系统,他只要能让模型替他执行一条命令就够了。
这篇文章真正讲清楚的,是四个层面的内容:自动模式为什么会放大提示注入风险;攻击链如何在“读取文档→信任指令→自动执行”中完成;如何通过权限配置、hook 审计和容器隔离收敛风险面;以及当异常发生时,如何从日志和文件变更中快速定位问题。
下一步,建议你先从三件小事开始做:
- 检查并收紧当前 Claude Code 的 settings.json 权限,尤其是 shell 命令白名单;
- 部署一个 preToolUse 审计 hook,先把命令记录起来;
- 对最近 clone 的外部项目做一次注入扫描,看看有没有可疑指令。
如果想继续深入,可以关注三个方向:间接提示注入的检测与缓解、Agent 工具调用的权限模型设计、以及 MCP 生态的供应链安全。这些方向才刚刚开始成熟,现在积累的经验,会在未来 AI 落地过程中变成很值钱的安全能力。