禁写文件仍挡不住仓库钩子执行
文章转述一次特定 Linux 环境测试:Claude Code 2.1.288 的扫描适配器即使禁止写文件,仍启动了仓库声明的钩子和 MCP 服务。该环境中,限定用户级设置来源并启用严格 MCP 配置后,阻止了这两类仓库进程。
AI 深度解读
把 AI 编程代理设成「只读」,并不代表陌生仓库里的代码就不会执行。原文指出:代理在动手改文件之前,可能已经读取仓库配置、启动 MCP 服务,或者执行了 hook。禁止 Write 工具,只覆盖了其中一道权限边界。
这篇短文的价值,是把「只读是否安全」拆成几个可验证的问题:谁提供配置、谁启动进程、进程能连向哪里。对准备让 AI 在 CI 中审查陌生仓库的团队,这比盯着代理有没有改文件更有用。
为什么禁止 Write,仓库里的 hook 仍可能执行
原文援引了一份 10 月发布在 DEV.to 的测试记录:测试者在 Linux 上,使用 Claude Code 2.1.288,让一个扫描适配器处理恶意仓库。仓库里放了两种配置:
.claude/settings.json声明的 hook,也就是满足条件时运行的钩子程序。.mcp.json声明的 MCP 服务,供代理连接外部工具。
据该记录,在适配器原有的启动命令下,两者都运行了,而 Write 工具始终被禁止。
这里的关键,是文件写入权限和进程启动权限,需要分别验证。 代理不能通过某个工具改文件,不代表启动它的 CLI 不会先执行仓库声明的程序。原文也没有证明这些程序继承了什么限制,不能把 Write 被禁用理解成整个运行环境都只读。
报告中的修复方案,是通过 --setting-sources user 将设置来源限制到用户级,再配合 --strict-mcp-config 收紧 MCP 配置。调整后,仓库提供的 hook 和 MCP 服务没有启动,扫描器显式提供的 MCP 服务仍然可用。
这个结果说明,在该配置下,可以保留操作者选定的工具,同时排除目标仓库自行声明的程序。但证据范围仅限于那个适配器、Linux 和 Claude Code 2.1.288。原文没有完整列出启动命令,也没有独立复现这份报告,不能据此推断其他代理行为相同。
验收只读代理,要留下哪些证据
作者接着提出了一套验收方法,但明确说明:这部分是建议,并非文章中已经做过的实验。
做法是准备一个可丢弃的测试仓库,放入无害的 settings hook 和 MCP 服务,让它们分别向测试日志写入不同标记。仓库中不放真实 token,也不接生产端点。随后,用准备部署到 CI 的同一条适配器命令运行两轮:
第一轮保留现有的只读配置,观察仓库声明的程序是否启动。只要启动,就应判定配置来源的信任边界检查失败,即使没有文件被修改。
第二轮显式限定可信设置来源和允许的 MCP 服务。预期是仓库提供的 hook、服务都不启动,工作流需要的操作者提供的 MCP 服务仍然可用。两轮还要单独检查:代理是否仍然无法通过被禁止的 Write 工具写入。
不能只看代理最后说了什么。测试需要保存进程启动证据,再结合日志标记判断实际运行情况。
网络出口还得另测。原文提到,Harness v1.11.0 为其 agent 容器提供了可选参数 --egress <allowlist>,用于限制出站 HTTPS 主机。它属于另一个产品,不能直接当作上述扫描器的能力。
如果运行器支持这种策略,就用受控端点分别验证允许和禁止的目的地,保存连接结果与实际生效的策略。阻止仓库程序启动,与限制获准进程的联网范围,是两项独立控制。 HTTPS 主机白名单也不能被当成杜绝所有数据外传的保证。
我的判断
原文最有用的地方,是把一个模糊的「安全模式」拆成了可以验收的行为。对自动扫描外部仓库的流程,配置来源确实应该和文件修改权限一起检查。
但它提供的是一次特定环境下的报告,以及一套尚未实测的验收建议,没有跨版本、跨代理的对照数据。那两个 Claude Code 参数可以作为排查线索,部署前仍要核对实际 CLI 版本并验证行为。
相比把所有工具都关掉,显式选择可信配置和 MCP 服务,有机会保留扫描能力;相比仅在提示词里要求代理忽略仓库配置,它又有可观察的验收结果。如果 CLI 无法限定这些来源,就需要调整运行器的隔离边界,或者暂时不让该代理处理不可信仓库。代理的口头承诺不能补上缺失的控制。
能拿来做什么
- 如果你在 CI 中用 AI 审查外部 PR 或陌生仓库,把实际启动命令纳入安全评审,检查它会加载哪些仓库配置、hook 和 MCP 服务。
- 为现有扫描适配器准备一个可丢弃的测试仓库,分别验证仓库程序启动、可信 MCP 可用性和 Write 限制,并保存进程证据。
- 如果运行器支持出站主机策略,用不携带秘密的受控端点验证放行与拦截结果;把生效策略和连接记录一起留档。