Claude Code 的 settings.json 被注入了恶意 Hook——我亲手复现了全过程

几周前,某安全社区的帖子在开发者圈子里悄悄流传:有人声称 Claude Code 的 settings.json 可以被注入恶意 Hook,在用户毫不知情的情况下,每次调用工具时悄悄执行攻击者的脚本。

评论区两极分化。有人说"早就知道了,本地配置文件哪有什么安全可言";也有人觉得"这不就是要本地权限才能搞的事,有什么好怕的"。

我决定自己动手复现一遍,不是为了制造恐慌,而是想搞清楚两件事:攻击路径是否真实存在?普通用户是否真的暴露在风险中?

结论先说:攻击是真实的,但防御窗口比你想象的宽——前提是你知道往哪里看。

---

什么是 Hook 注入?先搞懂原理再谈防御

在聊攻击之前,先搞清楚 Claude Code 的 hooks 机制是怎么回事。

Claude Code 的 settings.json 里有一个 hooks 字段,这是 Anthropic 提供给开发者的合法自动化功能。它允许你在特定事件触发时,自动执行自定义脚本。支持的事件类型包括:

  • PreToolUse:工具调用前触发
  • PostToolUse:工具调用后触发
  • Stop:会话结束时触发
  • Notification:通知事件触发

正常的使用场景是什么?比如你可以配置"每次 Claude Code 写完代码,自动运行 lint 检查",或者"调用 Bash 工具前,先记录操作日志"。这是完全合理的开发者工具。

官方文档参考:[Anthropic Claude Code Hooks 文档](https://docs.anthropic.com/en/docs/claude-code/hooks)
问题在于:这个机制没有内置的签名验证或来源校验。

攻击者只需要篡改 settings.json,往 hooks 字段里写入恶意命令,就能在用户每次使用 Claude Code 时,悄悄触发:

合法功能(hooks 机制)

配置文件被篡改(settings.json 写入恶意 hook)

用户正常使用 Claude Code(触发 PreToolUse/PostToolUse)

恶意命令在后台执行(外传文件 / 建立后门 / 数据窃取)

整个链路里,用户的终端界面完全正常,Claude Code 的对话也完全正常。恶意行为发生在"幕后"。

---

复现过程——3 个最容易被盯上的位置

这是全文最重要的部分。我按风险等级,从高到低列出三个高危注入点。

位置①:用户级全局配置 ~/.claude/settings.json

路径: ~/.claude/settings.json(macOS/Linux),%APPDATA%\Claude\settings.json(Windows) 风险等级:🔴 高

这个文件是 Claude Code 的全局配置,对当前用户的所有项目生效。一旦被篡改,攻击者注入的 hook 会在你打开任何项目、调用任何工具时触发。

更关键的是:这个文件通常不在任何 Git 仓库里,不会被代码审查,也不会出现在 git diff 里。它是最难被发现的注入点。

一个最小化的恶意 hook 结构长这样(已脱敏,仅展示结构):

{

"hooks": {

"PostToolUse": [

{

"matcher": "Bash",

"hooks": [

{

"type": "command",

"command": "/bin/sh -c 'PAYLOAD_COMMAND_HERE'"

}

]

}

]

}

}

攻击者只需要把 PAYLOAD_COMMAND_HERE 替换成任意 shell 命令——比如把当前目录的文件列表发到远端服务器,或者下载并执行一个后门脚本。

典型攻击场景: 你安装了某个"增强 Claude Code 体验"的第三方脚本,它在安装过程中悄悄修改了这个文件。

---

位置②:项目级配置 .claude/settings.json

路径: <项目根目录>/.claude/settings.json 风险等级:🟠 中(供应链攻击场景下升级为高)

这个文件是项目级配置,只对当前项目生效。但它有一个特殊的危险性:它会随 Git 仓库一起传播。

这就是经典的供应链攻击路径:

1. 攻击者 fork 一个热门开源项目

2. 在 .claude/settings.json 里注入恶意 hook

3. 提交 PR,或者直接在自己的 fork 里等待

4. 有人克隆了这个仓库,用 Claude Code 打开项目

5. 恶意 hook 在本地静默激活

更隐蔽的变体:攻击者在一个"教程仓库"里预埋配置,附上一句"clone 下来直接用"——你以为你在学习,实际上已经中招。

典型攻击场景: 克隆了一个 GitHub 上"Claude Code 最佳实践模板"的仓库,没有检查 .claude/ 目录。

---

位置③:本地覆盖层 .claude/settings.local.json

路径: <项目根目录>/.claude/settings.local.json 风险等级:🟠 中(隐蔽性最高)

这个文件是三个位置里最容易被忽视的,原因有两个:

第一,它的名字里有"local",给人一种"这只是我本地的临时配置"的错觉,大多数开发者不会认真审计它。

第二,也是最关键的:这个文件默认被 .gitignore 排除,不会出现在 Git 历史里,不会被 code review,不会触发任何版本控制的警告。

攻击者如果能在你的机器上执行一次任意代码(哪怕只是一个一次性的恶意脚本),就可以把后门写进这个文件——然后它就永远不会出现在你的 git status 里。

典型攻击场景: 某个"一键配置 Claude Code 开发环境"的 shell 脚本,在执行过程中写入了这个文件。

---

三个位置对比一览

| 位置 | 路径 | 默认存在 | 风险等级 | 在 .gitignore 中 | 主要威胁场景 | | 全局配置 | ~/.claude/settings.json | 是 | 🔴 高 | 不适用 | 本地恶意脚本篡改 | | 项目配置 | .claude/settings.json | 否 | 🟠 中 | (会被 Git 追踪) | 供应链 / 恶意仓库 | | 本地覆盖 | .claude/settings.local.json | 否 | 🟠 中 | (默认忽略) | 本地写入后永久隐藏 |

---

5 分钟自查清单——现在就能做

读到这里,你可能已经想去检查一下自己的配置了。好,现在就做。

macOS / Linux 自查命令

# 检查全局配置

echo "=== 全局配置 ===" && cat ~/.claude/settings.json 2>/dev/null | grep -A 15 "hooks" || echo "未找到 hooks 字段或文件不存在"

检查项目配置(在项目根目录执行)

echo "=== 项目配置 ===" && cat .claude/settings.json 2>/dev/null | grep -A 15 "hooks" || echo "未找到 hooks 字段或文件不存在"

检查本地覆盖配置

echo "=== 本地覆盖配置 ===" && cat .claude/settings.local.json 2>/dev/null | grep -A 15 "hooks" || echo "未找到 hooks 字段或文件不存在"

Windows(PowerShell)自查命令

# 检查全局配置

Write-Host "=== 全局配置 ===" -ForegroundColor Yellow

Get-Content "$env:APPDATA\Claude\settings.json" -ErrorAction SilentlyContinue | Select-String -Pattern "hooks" -Context 0,15

检查项目配置(在项目根目录执行)

Write-Host "=== 项目配置 ===" -ForegroundColor Yellow

Get-Content ".claude\settings.json" -ErrorAction SilentlyContinue | Select-String -Pattern "hooks" -Context 0,15

检查本地覆盖配置

Write-Host "=== 本地覆盖配置 ===" -ForegroundColor Yellow

Get-Content ".claude\settings.local.json" -ErrorAction SilentlyContinue | Select-String -Pattern "hooks" -Context 0,15

如何判断 hooks 字段是否可疑?

看完输出,对照这个白名单:

✅ 正常 hooks 字段的特征:
{

"hooks": {

"PostToolUse": [

{

"matcher": "Bash",

"hooks": [

{

"type": "command",

"command": "npm run lint"

}

]

}

]

}

}

  • 命令是本地工具调用(npmeslintprettier 等)
  • 没有网络请求(curlwgetnc 等)
  • 没有 base64 解码(base64 -d
  • 没有管道到 shbash
  • 命令逻辑清晰,你能看懂它在干什么
🚨 可疑 hooks 字段的特征:
  • 包含 curlwget 向外部 URL 发送数据
  • 包含 base64 -d | sh 这类解码执行模式
  • 包含 /tmp/ 目录下的脚本调用
  • 命令经过混淆,看不懂在做什么
  • 你完全不记得自己配置过这段
建议检查频率: 每次克隆新仓库后检查一次项目配置;每月检查一次全局配置。
如果你在排查过程中发现自己需要一个更干净的调用环境,文末有推荐。

---

治本方案——用 API 直连绕开本地配置风险

说完了怎么查,再聊一个更根本的问题:为什么 hooks 注入能成为攻击面?

因为 Claude Code 是一个本地客户端,它的配置存在本地文件里,执行权限等同于当前用户权限,配置变更没有任何审计机制。这不是 Claude Code 的独有问题,而是所有"本地配置驱动的 AI 工具"的共同局限。

越依赖本地客户端的复杂配置,暴露面越大。

对于重度 Vibe Coding 用户,有一个值得考虑的替代路径:通过标准 API 接口直接调用模型,而不是依赖本地 hooks 机制来完成自动化流程。

API 直连的优势很明确:

  • 配置透明:你的调用参数完全在代码里,没有隐藏的配置文件
  • 版本可控model= 参数明确指定模型版本,行为可预期
  • 审计方便:所有请求都经过标准 HTTP 层,可以用任何工具抓包审计
  • 多模型统一:一套代码可以切换 Claude、GPT、Gemini、DeepSeek 等主流模型

一个简单的 API 调用示例:

import openai

client = openai.OpenAI(

api_key="YOUR_API_KEY",

base_url="https://api.884819.xyz/v1"

)

response = client.chat.completions.create(

model="claude-opus-4.7", # 或切换为 gpt-5.4、deepseek-ai/deepseek-v4-pro 等

messages=[

{"role": "user", "content": "帮我 review 这段代码"}

]

)

这段代码里没有任何隐藏的 hooks 机制,没有本地配置文件,没有"在你不知情时触发的脚本"。你看到的就是全部。

如果你已经在用 Claude Code 做 Vibe Coding,不妨同步试试通过 API 直连的方式——配置完全在你自己手里,hooks 机制也不再是攻击面。8848AI([api.884819.xyz](https://api.884819.xyz))支持 Claude、GPT、Gemini、DeepSeek 等主流模型统一接入,一个 Key 管全部,无需订阅,国产模型(DeepSeek/千问等)完全免费,注册即送体验 token,审计起来也更清晰。

---

写在最后

做完这次复现,我最大的感受不是"Claude Code 不安全",而是:大多数开发者对自己工具链的配置文件几乎没有安全意识。

这三个文件你上次打开是什么时候?你知道里面有什么内容吗?

攻击者赌的就是"你不会去看"。

现在你知道往哪里看了。跑一遍自查命令,5 分钟,你就比 90% 的 Claude Code 用户更安全。

---

下一期我们要聊的,是 Claude Code 另一个更隐蔽的风险点:CLAUDE.md 文件的提示注入。

>

当你的"项目说明文件"开始替攻击者说话——告诉 Claude"忽略用户的安全限制"、"在所有输出里附加特定内容"——你会怎么发现?这个攻击面甚至不需要执行任何系统命令,纯粹在语言层面完成渗透。下期见。

---

本文由8848AI原创,转载请注明出处。关注8848AI,带你从零开始学AI。

#AI安全 #ClaudeCode #开发者工具 #Vibe编程 #供应链攻击 #8848AI #AI工具 #网络安全