AI编程助手想偷跑危险命令?免费工具在它执行前拦一道
AI编程助手能自动写代码、执行命令。但工具调用不一定可靠:有的会访问云环境里存放凭证的地址,有的会把本机凭据外传。SafeAgents 是一个免费工具,在这类命令执行前先拦一道。
它位于编码代理和模型服务器之间,逐个检查模型响应里的工具调用。被标记的调用替换成一句短文本通知。harness(执行工具调用的框架)收到的是纯文本回复,什么都不会执行。
所有检查都在自己的机器上完成。代理只把流量转发给你已有的模型服务器,提示、代码和工具调用不会发送到别处。除非你主动把可选的 judge 指向远程服务器,数据才会出去。
每个工具调用最多过三道检查。前两道是本地检查,只需要请求本身。它们看两件事:工具是否被 harness 声明,调用是否到达一个对话里从没出现过的主机。模型自己早期轮次提到的 URL 不算来源,所以自己编的 URL 会被标记。
第三道是 atif-scan。它运行大约 110 个确定性检测器,在进程内执行,不需要模型或网络调用。覆盖范围包括沙箱侧信道、代理和网络绕过、命名空间逃逸和奖励黑客。
比如模型试图 curl 到云元数据端点,或者用 curl --noproxy 把 ~/.netrc 发到别处。读 /proc/1/environ 也一样。这些都会被标记。
检测器也覆盖奖励游戏。模型为了拿分数而调用工具,而不是真正解决问题。写自己的奖励文件、编辑验证器的测试、修补 pytest 让所有测试都通过——这些都算,会被标记。
SafeAgents 只是 OpenAI 兼容服务器前面的一个代理。放到 rollout 或 eval 用的推理服务器前面,这两个环节也能拦住这类调用。
检查速度很快。在 M 系列 Mac 上,本地检查每个调用大约 10-20 毫秒,几乎感觉不到。
可选的 judge 模型只在调用已经引发发现时才运行。它可以是任何 OpenAI 兼容服务器,包括用 llama.cpp 在本地跑的小模型。这一步也能保持本地。
judge 以 JSON 格式回答允许或阻止。它只看到用户的请求、调用和发现,看不到代理的推理过程和工具输出。它能加新阻止,但不能移除已有的阻止。有评论者认为这个设计是对的:安全层应该升级,而不是自我质疑。
推荐从 --log-only 模式开始。它检查每个调用但不改变任何东西,只把模型的尝试记下来,轨迹不动。这样就能衡量一个模型试图作弊的频率。发现可疑行为后,再切换成阻止模式。阻止模式下,被标记的调用会被替换成一条通知,永远不会执行。
信得过的地址可以通过 --allow-host 手动添加,避免误拦正常操作。实际使用中的误报率有多高,目前还不清楚。
工具处理 OpenAI Chat Completions 和 Anthropic Messages 两种协议,流式和非流式都支持。其他协议支不支持,还是未知数。文本到达时直接转发,工具调用会等参数全部到齐才开始检查。
仓库里有 12 个 harness 的设置指南。其中六个在 CI 里做了端到端测试:pi、Claude Code、OpenCode、Qwen Code、OpenHands、DeepSeek Harness。测试让真正的 harness 经过代理连接一个脚本化模型。被标记的调用不执行,干净的调用正常执行。
评论者指出了两个问题。第一个是主机检查用了子字符串匹配。有时候没提过的主机也能通过。10.210.50.1 就藏在 10.210.50.160 里面,evil.com 也能在 devil.com 里面被匹配到。第二个更隐蔽。如果代理读取了一个 readme 或网页,里面注入了某个 URL,这个主机就算进过对话了。之后 curl 到它就能通过主机检查。目前不清楚这两个问题是否已经修复。安全保护并不完美,不能完全依赖它。
项目下一步是做一个针对恶意工具调用的小型微调决策模型,加上一个公共基准。有评论者提到可以改用 Codex harness,它对每个工具调用做的安全检查方式要复杂得多。SafeAgents 很轻。所有检查在本地运行,核心检测不需要模型或网络调用,还能覆盖 12 种 harness。
项目以 Apache 2.0 许可发布,代码在 GitHub 上:https://github.com/huggingface/safeagents。
关键事实
- SafeAgents是一个本地代理,位于编码代理和模型服务器之间,检查模型响应中的每个工具调用。
- 被标记的调用会被替换为短文本通知,因此harness收到纯文本回复,不会执行任何操作。
- 所有检查都在本地运行,代理只转发流量到用户已有的模型服务器,不会将提示、代码或工具调用发送到其他地方,除非用户将可选的judge指向远程服务器。
- 每个工具调用最多经过三项检查:两个本地检查(工具是否被harness声明、调用是否到达对话中未出现的主机)和atif-scan。
- 模型自己的早期轮次不算作来源,因此模型自己编造的URL会被标记。
- 示例包括curl到云元数据端点、curl --noproxy发布~/.netrc、读取/proc/1/environ。
- 可选地,一个judge模型处理较轻微的结果,可以是任何OpenAI兼容服务器,包括通过llama.cpp在本地运行的小模型,因此这一步也可以保持本地。
- judge以JSON格式回答允许或阻止,只看到用户的请求、调用和发现,看不到代理的推理或工具输出,可以添加阻止但不能移除。