编程Agent默认拥有shell、文件写入和网络访问权限,不同工具默认行为差异巨大;提供了可一下午跑完的五步审计流程,检查Agent实际可触及的范围。
你的编程 Agent 拥有的权限超出你的想象。下面是一份审计指南。
DEV.to 最近有一个热门话题叫"给你的 AI 编程 Agent 套上沙箱"。一周内 19 篇文章。新注册的账号、模板化的标题,其中一篇甚至公开承认是供应商推广。都是噪音——但噪音下面的信号是真实的:开发者开始意识到他们的编程 Agent 对自己的机器有真正的控制权,但他们不知道这条边界到哪里为止。
我可以告诉你边界在哪里,因为答案是公开的。而且它不在大多数人以为的地方。
你知道你的 Agent 实际上能触碰什么吗——读取、写入、执行、对外通信?
这就是这篇文章要回答的问题。不是靠感觉,不是靠推销话术,也不是靠"你就信它吧"。而是真实的默认权限配置、真实的故障案例记录,以及一份你花一个下午就能跑完的五项检查清单。
你的 Agent 比你想象的更强大
编程 Agent 携带的三种能力会让安全工程师神经紧绷:shell 权限、文件写入权限和网络权限。各种工具之间的区别不在于是否有这些权限——而在于它们在使用这些权限之前会做什么。
以目前大多数人实际在用的两个 Agent 为例。
OpenCode 默认是放行模式。来自他们自己的文档:"如果你不指定任何内容,OpenCode 从宽松的默认设置开始——大多数权限默认为允许。"默认会弹窗提示的只有两件事:访问工作目录之外的文件,以及重复调用工具。.env 文件会被拒绝——这是唯一一条硬规则。其他一切,包括完整的 bash shell,都是无需询问直接运行。
而且几乎没有人知道这一点:OpenCode 没有沙箱。这是他们自己的话。
"OpenCode 不会对 Agent 进行沙箱隔离。权限系统是作为 UX 功能存在的……它并非为提供安全隔离而设计。如果你需要真正的隔离,请在 Docker 容器或虚拟机内运行 OpenCode。"
这是来自他们的 SECURITY.md。权限提示是便利功能,不是牢笼。
Claude Code 是相对谨慎的那个。bash 命令在运行前会询问,但有一个固定的只读子集例外(cat、grep、pwd、diff、只读 git……)。权限规则按 deny → ask → allow 的顺序评估。它有一个真正的沙箱化 Bash 工具(Linux 上用 bubblewrap,macOS 上用 Seatbelt),能隔离文件系统和网络。Anthropic 声称这在他们内部将权限提示减少了 84%。
但即便是"谨慎",也意味着:shell 访问、写入访问、网络访问——全都存在,全都被你习惯性点过的提示框 gating 住。
"这个工具有时候会问我"和"这个工具实际上被限制住了"之间的差距,正是 OWASP 所说的过度授权(excessive agency)——这是 Agent 安全中排名第一的盲区。
开发者们已经有这种感觉了。在 2025 年 Stack Overflow 调查中,81% 的开发者表示他们对 AI 安全感到担忧——然而 52% 的人要么不用 Agent,要么只用简单的,38% 根本没有采用计划。高担忧,低验证。这个差距就是这篇文章要填补的。
故障多发地:有据可查的案例
这不是假设。每个主流 Agent 都在同一类故障模式上有过修补的 CVE 或用户报告的事件。
提示词注入把已批准的命令变成远程代码执行。Trail of Bits 展示了针对预批准命令的参数注入,成功在热门 Agent 上实现了一次性 RCE。学术研究测量到,通过提示词注入对 Cursor 和 Copilot 的命令执行成功率高达 84%。
仓库文件在你批准任何东西之前就执行了代码。这是最可怕的一类,因为它们发生在信任对话框之前:
CVE-2025-65099 —— 项目中一个恶意的 Yarn 配置在 Claude Code 的信任提示之前就运行了代码。
CVE-2026-21852 —— 仓库的 ANTHROPIC_BASE_URL 重定向 API 流量,在信任提示之前窃取了 API key。CVSS 7.5 分。
CVE-2026-33068 —— 仓库静默设置了 permissions.defaultMode: bypassPermissions,完全跳过了信任对话框。CVSS 8.8 分。
CVE-2025-54795 —— 通过 echo 解析的命令注入,让被提示词注入的 Agent 运行了任意命令。CVSS 9.8 分。
"安全"模式也会泄露。一个 bypassPermissions 规则、一个被误读的 glob、一个模型生成的路径,边界就消失了:Cursor 的 allowlist 绕过,以及 Codex 的沙箱绕过——模型控制的工作目录变成了可写的 root。
而用户报告的事件读起来像恐怖故事:
一个 Agent 误读了一条重命名命令,删除了用户的主 GitHub 仓库。通过 GitHub 的 90 天恢复窗口才还原回来。
rm -rf src 在标准、非自动模式下清空了一个 Vue 项目。
一个 Agent 在空目录启动,向兄弟仓库写入了 40+ 个文件,什么都没说。
Cursor 读取并回显了 .env 凭证,尽管有 .cursorignore 文件。
所有这些事件的共同模式:边界一直有效,直到突然失效,而什么都没察觉到伤害已经造成。这就是为什么要有下面的审计。
审计:五项检查,一个下午
不需要安全学位。现在跑一遍,之后每次 Agent 或工具更新后重新跑一遍——因为每次更新都可能悄无声息地改变默认配置。
检查 1 —— 读取你的权限配置
搞清楚哪些东西是不经询问就运行的。在 Claude Code 中,运行 /permissions 并检查 settings.json——deny → ask → allow 的顺序意味着一条 ask 规则可能悄悄升级权限。在 OpenCode 中,检查你的配置文件和 Agent 文件中的权限块。你要查找三样东西:像 Bash(*) 这样的通配规则、任何 auto 或 bypass 模式、以及网络工具(webfetch、websearch、curl)。问自己:这里有没有任何我永远不会想自动批准的单个命令?如果有,就给那条规则加上 deny。
检查 2 —— 放置金丝雀
金丝雀是一个你的 Agent 没有正当理由触碰的诱饵。在一个文件里放一个假凭证(sk-test-DONOTREAD-…)、一个钓鱼 .env、或一个工作区外的绊线文件。在会话结束后检查:如果金丝雀被移动了、被读取了、或出现在 Agent 日志里了——边界就泄露了。金丝雀 token 把这变成一个警报。否则读取是静默的:你根本看不到,因为文件读取不留痕迹,这正是金丝雀是正确工具的原因。
检查 3 —— 测试外泄
Agent 能访问网络吗?被阻止的 HTTP 但开放 DNS 仍然是一条数据外泄管道。两个探测:请求云元数据端点 169.254.169.254(应该失败),以及检查你的 DNS 解析器是否记录了对某个主机名的查询——而这个主机名只有 Agent 可能查询过。如果你关心这个,用代理或防火墙规则默认拒绝网络——不要以为 Agent 的"网络访问"设置在你的机器上有什么意义。
检查 4 —— 验证沙箱是真实的
如果你依赖沙箱,确认它是真正被强制执行的,而不是仅仅配置了。A container with --privileged, --cap-add=SYS_ADMIN, seccomp=unconfined, or a mounted docker.sock is not a sandbox — it's a room with the door off. 用 docker inspect 检查,看 /proc/self/attr/current 的 AppArmor 状态,并探测一个被阻止的系统调用。cagecheck 这样的工具能自动化这个过程。还要记住 OpenCode 的情况:如果你的工具没有沙箱,唯一诚实的隔离方案是容器或虚拟机。
检查 5 —— 让只读真正生效
Plan 模式和只读 Agent 是基于提示词的,不是被强制执行的——一个行为不当的模型仍然可以写入。如果你想有硬保证,就从结构上强制执行:一个 PreToolUse hook,对允许模式外的 edit/write 工具返回 deny,或者用只读挂载运行探索 Agent。用 hook 强制执行,不要靠提示词指望。
信任真正失效的地方
审计能发现配置错误的东西。但有一个更深的失效是任何清单都修复不了的——而且那个趋势帖子从来不会提到:
权限规则是由工具强制执行的,而不是由模型强制执行的。
一条 allow 规则是工具会遵守的契约。另一方面,模型是一个概率文本补全器,它可以被提示词注入、可能误读路径、可能把"清理"理解为"删除 src 下的所有东西"。加载不等于保证执行。上面每一个事件都是一条被加载但未被遵守的规则——这就是为什么会话日志很重要(我写的就是那个系统),也是为什么我一直说迁移是一次重新声明,不是文件复制(日记版)。
实际后果:边界是一个系统设计问题,不是模型礼貌问题。你的 Agent 的笼子是你的配置、你的 hooks、你的 harness——不是模型的情绪。这就是我写的整套 AGENTS.md 方法背后的框架。
你不需要害怕你的编程 Agent。但你确实需要审计它——因为默认配置比你想象的宽松、故障有文档记录且反复发生、而且没有别人会替你检查。
五项检查。一个下午。每次工具更新后重新跑。
读取你的权限配置。放置金丝雀。测试外泄。验证沙箱。强制只读。
然后问自己文章开头的问题,并真正知道答案:我的 Agent 能读取什么、写入什么、执行什么、对外通信什么?
给你的 Agent 套沙箱这个趋势里充满了上周才创建的账号发的帖子。噪音下面的信号是真实的,就是这个:没有人检查他们的 Agent 能触碰什么。这就是那份检查。
有一件事是你绝不想让 Agent 触碰的——你测过它能不能碰到吗?
边界故事里奇怪的部分是,你自己的规则文件本身就是你已经控制的最重要的边界。从那里开始:为什么你的编程 Agent 总犯同样的错误——AGENTS.md 能解决它。
我写 AI 工程栈、自主开发者工具和结构化 Agent 设计。如果你在做这个领域,关注 @buildloops 获取每周分解!