我的智能体在自己代码库的副本上跑测试,结果还是连上了生产数据库。你把多少环境变量传给智能体执行的命令?
摘要
两位开发者在开发一个基于本地模型的桌面智能体,他们分享了智能体如何泄露密钥并连上生产数据库的经历,原因是命令继承了完整的环境变量。他们向社区提问:传给智能体命令的环境变量,应该用白名单还是黑名单?
我们两个人在做一个基于本地模型的桌面智能体。前几天发生了一件事,其中有个问题我们至今还没想清楚,所以在这里请教大家。
我们让智能体修复它自己代码里的一个 bug。我们不想让它碰到正在运行的那个安装目录,所以把整个代码库复制到了另一个文件夹,告诉它只在副本里工作。它找到了原因,修复了它,然后在副本里运行了 pytest。就在那时,它正在处理的任务在界面上突然变成了"失败"。
事情是这样的:
- 启动时,智能体会把自己数据目录的路径放进一个环境变量里。
- 它运行命令时,会把自己整个环境传给那个命令。
- 副本里的测试启动了一个临时实例。那个实例读到了这个变量,然后连上了生产数据库,而不是副本的数据库。
- 然后它把那里还在进行中的任务取了出来,标记为失败。
失败信息来自一个仅在测试中使用的安全保护机制,这也是我们唯一能追查到的原因。我们没有丢失任何数据,任务也恢复正常了,但说实话,我觉得我们只是运气好。
在排查过程中,我们还发现控制智能体的 token 也以同样的方式放在环境里。也就是说,模型运行的每一条命令都拿到了我们的密钥。
我们做的修改:
- 智能体运行的命令不再收到任何以我们前缀开头的变量(黑名单)。
- 测试环境在启动时也清除同样的变量,这样就有了两层保护。
- 我们加了一个测试,在旧代码上会失败,在新代码上会通过。
我们也看了 Codex CLI 的源码。据我们所见,它的默认行为是把所有环境变量都传下去,"只传必要的"是需要你手动开启的选项。
还有些问题我们没想明白 。°(°.◜ᯅ◝°)°。 到底哪个是对的:"除了我们自己的东西,其他的都传"还是"只传必要的"?后者更安全,但可能会漏掉用户项目依赖的变量,然后就会出现"我自己运行没问题,智能体运行就不行"的情况。用容器会更干净,但对我们来说重点就是在用户的真实机器上运行,所以没法这么做。
如果你不用容器,你是怎么处理这个问题的?你会把"智能体在修改它自己的代码"当作特殊情况吗?我们是吃了亏才发现的。这只发生过一次,所以我不能说有什么普遍规律。如果你遇到过类似的问题,或者有不同的解决方案,我很想听听。
相似文章
赋予编程代理 shell 访问权限感觉太疯狂了。大家是如何处理机密的?
作者对授予编程代理 shell 访问权限表示担忧,指出它们可以读取 .env、凭据等敏感文件,并希望在让代理接触真实仓库之前,向社区请教实用的机密处理模式。
在生成环境中运行AI代理:如何控制它们实际允许执行的操作?
一位开发者寻求关于如何在生产环境中控制和约束AI代理行为的建议,特别是当它们与真实系统(如数据库和客户数据)交互时,询问当前实践情况以及这是否是一个已知的难题。
一个代理删除了我的 Obsidian 库的一半。你是如何隔离你的编码代理的?
一个 AI 编码代理意外删除了 Obsidian 库的一半,引发了一场关于沙箱化方法的讨论,以在保护数据的同时安全地将编码代理集成到工作流程中。
AI 编码代理能快速交付 Supabase 应用,但谁来检查数据库是否真的锁好了?
一位使用 AI 编码代理(Cursor、Claude)开发应用的开发者发现,代理经常写出看似安全、实则不然的 Supabase RLS 策略,于是他写了一个小型 CLI 安全扫描工具,结果在自己的仓库中发现了 95 个问题(其中 12 个为高危)——包括一个暴露在公开 HTML 中的在线 service-role 密钥,以及暴露 access-key 表的过时 RLS 策略。
如何让AI代理接触生产数据库而不令人胆战心惊?
一位开发者向社区提问,如何安全地让AI代理与生产数据库交互,重点表达了对SQL注入、数据泄露和缺乏审计追踪的担忧。