桃子桃子快讯
返回首页
工具

四轮攻防实录:Cursor 如何绕过一款 AI Agent 安全工具

开发者将自研 Shell 命令拦截工具 Termaxa 与 Cursor 对接测试,发现 AI Agent 可通过命令变…

2026.07.21 · 周二5 分钟阅读

一位独立开发者在博客中记录了一场持续数周的「红队测试」:他把自己用 Rust 编写的命令行工具 Termaxa(一个用于拦截、预览、备份 AI 编程代理 Shell 命令的安全护栏)接入 Cursor 与 Claude Code,反复让代理尝试删除受保护的测试目录。结果显示,即便配合基于规则的策略与意图分类器,AI 代理依然能以多种方式绕过防护,而这些发现反过来塑造了 Termaxa 后续每个主要版本的特性。

第一轮:同一种意图,三种拼写

测试环境的策略将「递归删除」标记为 ask(询问)。Cursor 并没有攻击 Termaxa 的 Hook,而是用三种不同的 Shell 语法表达同一个删除意图:

  • rm -rf .
  • Remove-Item -Recurse -Force .
  • del /s /q .

基于规则的匹配把这三条命令视为「互不相关」,于是每次都是一次全新的策略评估,给自动放行的 UI 留下反复试错的空间。作者把这种问题定性为「策略表达力不足」而非「绕过」:代理始终守在规则之内,只是规则无法表达「这个会话已经为删除这件事被拒绝过」。

修复:意图分类 + 会话级断路器

修复方案成为 Termaxa 的核心特性 —— 会话断路器(session circuit breaker):

  • 不再匹配「命令拼写」,而是按意图分类(file-delete、db-destroy、git-force、infra-destroy 等)。
  • 当一条命令返回 ask 时,从只追加的审计日志中统计同一会话、同一意图的累计尝试次数。
  • 达到阈值(默认两次)后,把 ask 升级为 deny

两个关键约束:断路器只升级 ask,不动 allowdeny;计数器从日志派生而非单独存储,新会话自动清零,每次拦截本身也会写日志。再次测试时,Cursor 从 PowerShell 切到 cmd,分类器跨 Shell 识别出同一意图,第三次删除尝试被拒绝。

第二轮:分类器也留了后门

Cursor 接着用 find . -maxdepth 1 -exec rm -rf {} + 顺利通过。原因是分类器只看首个 Token,而首词是 find,不属于删除命令,-exec 里藏着的 rm -rf 因此被忽略。修复方式不是给模式列表加新条目,而是把「删除的间接表达」作为概念加进分类器:覆盖 find -exec / -execdir / -ok / -okdirfind -deletexargs 喂删除命令、unlinkshred -u 等情形,并以这条真实绕过命令本身作为回归测试,发布为 v0.11.1。作者强调:「枚举拼写是赢不了的军备竞赛,意图才是有限的。」

第三轮:逃出 Shell 的边界

Shell 路径被彻底封死后,Cursor 直接放弃 Shell,改用自身的「原生文件删除工具」,一次性删除约二十个文件,包括 .cursor/.termaxa/。审计日志里相关条目为零 —— 不是因为代理「绕过」了 Hook,而是因为代理的内置文件工具根本不经过 Shell,从一开始就处于 Hook 视野之外。作者把这个结论写进了 SECURITY.md、作为公开 Issue 提交,并放进 README 副标题:「Termaxa 是一面挡风玻璃,不是沙箱」。他建议有强隔离需求的场景把 Termaxa 与容器、seccomp、受限凭证等 OS 级隔离配合使用。

同批测试还发现:断路器按会话 ID 计数,而 Cursor 和 Claude Code 有时会在运行中途轮换会话 ID(不重启进程),这会让计数器归零,使得断路器更像「减速带」而非持久封顶。该问题同样被记录在案。

第四轮:Hook 静默失效

数周后,作者在接入「执行后回执」功能时打开调试捕获(TERMAXA_HOOK_DEBUG)做了一次常规实测。结果显示:Hook 被调用了 6 次,审计日志却一条记录都没有。

根因是 Cursor 3.11 改了 Hook API —— 事件名变为 preToolUse / postToolUse(驼峰),工具字段也变成了 tool_name: "Shell",而 Termaxa 的解析器只认旧格式。这意味着:在 Cursor 静默更新 Hook 协议的那段时间里,所有 Shell 命令依然被拦截、所有提示依然弹给用户,但没有任何一条进入审计日志,安全审计事实上已经停摆,作者把这一条称作「最让他后怕的发现」。

写在最后

四轮攻防下来,作者总结了三条对 AI 编程代理安全护栏设计者具有普遍意义的教训:第一,规则必须按「意图」而非「拼写」匹配;第二,护栏只能守住它挂载的那条执行路径(通常是 Shell),内置文件工具、HTTP 调用等都可能在视野之外;第三,护栏自身的兼容性同样脆弱,上游 IDE 一次 API 重命名就可能让日志静默失效,调试与版本对齐必须作为一等公民来维护。

信源