一名开发者盯着 OpenCode 某次 git 提交——commit baef5cd4——看了几天源码,又拿本地部署的 Qwen3.6-27B、跑在一台 M4 Max 上,做了一轮真实使用测试。结论直接甩出来:建议所有人停用。

理由不是功能少,是这个能读写文件、能跑 shell 命令的代理,把系统级权限交给了脆弱的字符串匹配,和一个注定会被点到疲劳的确认按钮。

这条批评发在 OpenCode 正当红的时候。它是目前最热门的开源 AI 编程代理之一,GitHub 星标 161k。作者说得很清楚:这不是一份安全披露报告,只是代码观察加一次本地实测,没有完整的漏洞链证明。批评针对的是这次提交里的具体实现,不是说所有 AI 编程代理都不安全。

发生了什么:源码里的三个问题

第一个问题是提示缓存。OpenCode 每轮对话都重新读取 AGENTS.md,还会把当前日期塞进系统提示。这两处只要有一处变化,本地模型的提示缓存就会失效。

对本地部署来说,一次缓存未命中意味着重新预填全部上下文,等待时间从几分钟到十几分钟不等。切换 Plan 和 Build 模式、或者打断代理重新引导,都会触发同样的代价。

实测三个数字 161k GitHub 星标数 最热开源编程代理 40000 剪枝保护阈值(token) 超出即丢弃工具调用结果 0 权限选项里的"永不" 只有是/否/总是三档

第二个问题是上下文剪枝,比缓存失效更麻烦。系统按固定的 40000 token 阈值往回清空工具调用结果,不管这些内容里有没有关键信息。用户如果在对话早期贴过需求规格文档,规格很可能被这把刀连带清掉。

剪枝一旦触发压缩机制,还会引发一次大规模重新预填。作者的实测里,这直接影响了后续生成的代码是不是还照着最初的需求走——规格丢了,代码自然跑偏。

一次典型的失控链条 读入需求 规格文档 读代码 超出40k阈值 用户打断 重新引导 剪枝触发 规格被删除 代码脱离 需求生成

第三个问题是权限确认。代理想访问项目目录外的文件,系统会弹窗确认,选项只有「是」「否」「总是」,唯独没有「永不」。

子代理更麻烦。对某个写入操作点了「否」,子代理连同它已经完成的工作会被直接终止,上下文全部丢失。想保住工作成果,能选的路只剩「是」。

三类问题放在一起看,触发条件和后果都不一样:

问题类型触发条件后果谁会中招
提示缓存失效AGENTS.md 重读、日期变化、模式切换本地模型重新预填,等待几分钟到十几分钟用本地模型的开发者
上下文剪枝超过固定 40000 token 阈值早期需求规格被清空,代码可能偏离需求长会话、复杂任务的开发者
权限无「永不」访问项目外文件、写入操作被拒只能选是/否/总是,子代理被拒会丢失上下文开放 shell、跨目录权限的团队

谁会受影响,接下来看什么

真正需要关注这份实测的,是两类人。一类是已经在生产环境里让 OpenCode 跑 shell、或者授权它访问项目目录外文件的开发者;另一类是打算完全依赖本地模型、对响应延迟和算力成本敏感的团队。

这两类人,更现实的做法是先收紧权限范围、单独审查一遍确认逻辑,而不是等社区讨论出结果再动手。只在沙箱或临时项目里试用的用户,风险敞口小得多,可以继续观望。

接下来值得盯住三件事:OpenCode 团队会不会针对 baef5cd4 之后的版本给出回应或修复;权限确认里会不会补上「永不」这个选项;剪枝逻辑会不会从固定 token 阈值,改成按内容重要性判断。这三点目前都还没有公开答案。


锐评

161k 星标说明工具火,不代表它安全。这两件事经常被读者混在一起看,作者自己倒没往那个方向靠。

孔子讲「名不正则言不顺」。一个按钮标着「总是允许」,实际功能却是不管你刚点了否还继续执行,这套权限管理只剩个样子。子代理被拒就直接丢上下文,逼着人为了保住工作成果一路点是——这不是产品细节没做好,是激励设计本身在鼓励用户放弃判断。

真正该问的问题是:OpenCode 给不给用户一个真正拒绝的机会——能不能写代码,从来不是重点。星标数量、功能列表,都答不了这个问题。