Skip to content
实验报告
待周评
凭证不再写成文件,就真的隔离了吗?
开源工程观察 · 实验研究

凭证不再写成文件,就真的隔离了吗?

一组固定版本实验表明,文件写入归零可能只是秘密换了一条传递路径。判断隔离,要看接收方最终能拿到什么。

2026-09-10English →

凭证不再写成文件,就真的隔离了吗?

一次凭证修复,把文件写入回调从四个降到了零。只看这个数字,似乎可以宣布:运行 Claude 的进程,再也不会接触其他模型提供方的凭证了。

可在我们的受控实验里,同样四个模拟凭证,全部出现在接收子进程的环境变量中。

这里没有出现神秘的绕过。秘密没有被删除,只是换了一种递交方式。它提出了一个更具体的问题:当我们说“凭证隔离”,究竟在限制文件放在哪里,还是限制一个进程能够取得哪些值?

一个合理修复,为什么不能承担另一个承诺

OpenHands Agent SDK 可以通过 ACP——一种连接 Agent 客户端与执行程序的协议——启动不同的模型工具。SDK 需要适配这些工具不同的认证方式:有的读取环境变量,有的读取认证文件。

PR #4927处理的是文件型凭证的归属。默认配置汇集了多个提供方的文件规则;候选修复按实际提供方筛选,避免启动一种工具时,顺便物化另一种工具的认证文件。这个目标有独立价值:少写无关文件,也避免错误的数据目录配置。

但文件规则不是秘密授权名单。启动代码还会把注册表中的其他秘密递交为普通环境变量。修复缩小文件集合的同时,也缩小了“从环境变量递交中排除”的集合。于是,一项秘密可以从文件出口消失,却重新出现在环境出口。

这不是修复失败的同义词。#4927 的目标是纠正文件处理的归属,我们不能替它增添“所有其他提供方的秘密均不可见”这一更强承诺。

把观察点放到接收进程

我们固定该 PR 的 基线(base)与候选(head)版本,运行原始筛选方法、环境冲突处理方法,以及启动方法中连续的环境构造代码。两个版本共用从 head 源码提取的注册表元数据,以集中比较处理逻辑;提供方身份由测试替身指定,不验证真实命令探测。输入只有合成字符串,不使用真实凭据。

文件物化由记录回调的夹具替代,因此下表的“文件端”不是磁盘上实际创建的认证文件。环境端则交给真实 Python 子进程;子进程只列出变量名,不连接模型、不尝试认证。

版本与接收方文件端回调数接收进程可见的凭证内容变量数
修复前,Claude40
候选修复,Claude04
修复前,Codex40
候选修复,Codex13
候选修复,未识别提供方40

两轮输出一致。四类凭证内容变量 对应注册表中的 Codex、Gemini、Kimi、Pi 文件型凭证。Codex 的一项留在文件路径,另外三项进入普通环境变量;无法识别提供方时,候选方法保留全部文件规则。这些行为都应按各自分支解释,不能用“只留本提供方”概括整个函数。

文件端计数和环境端计数必须同时观察

图 1:图示采用本地接缝实验数据。它证明模拟值经过所测构造路径到达子进程,不证明真实 CLI 使用了这些值,更不证明秘密已经发往外网。 来源:本轮固定源码实验的第 1、2 轮保存观测。

空名单,也要读清楚例外

另一个 Draft PR #4931讨论不同层级:Agent 配置可以限制会话接收的秘密名称。它在服务端过滤注册表,因而有机会同时收窄后续的文件和环境变量两条路径。

我们把这份 PR 的原过滤函数接到前面的环境片段之前,做一次明确标注的跨 PR 实验组合。两项变更尚未合并,不能把这个组合写成某个已发布 SDK 的行为。

同样的六项合成输入,在 Claude ACP 配置下得到:

配置中的 secret_refs过滤后留下什么
null原来的六项
[]本提供方的 ANTHROPIC_API_KEY
[PROD_DB_URL]业务数据库变量,加本提供方的认证变量

空列表没有留下业务秘密,却保留了认证例外。这个例外是代码显式设计的:ACP 工具仍需要认证才能工作。相对地,我们只运行普通 OpenHands 配置的空列表过滤函数,所得集合为空;这项对照没有经过 ACP 启动路径。

所以,“空名单”应在接口上被解释为准确的产品含义。用户若把它理解为“此进程不接收任何秘密”,就会对系统形成错误预期。能够继续认证和能够读取业务凭证,是两种需要分别说明的能力。

还有一条不经过注册表的路

注册表变小,也不保证最终环境只剩这些值。所测启动片段还合并宿主环境。我们给这条入口放入一个独立的合成标记,在上述所有 ACP 场景中,它仍然到达子进程。

这并非生产泄露记录。实验只说明,注册表过滤管不到一个绕开注册表的输入;#4931 的作者也明确把宿主环境继承列为未解决范围。下一步审查需要枚举全部传递渠道,而不能给一个配置字段赋予覆盖整个进程的意义。

一个可操作的验收方式是:先确定这个提供方、这次运行需要哪些业务秘密和认证材料,再在最终进程边界观察实际环境与文件能力。文件格式转换留在授权之后。提供方未知时采用什么策略,也必须单独定义;“无法分类”不应在产品说明里被悄悄写成“已经隔离”。

这组实验没有测试完整 SDK、真实 ACP 握手或认证,也没有验证服务端请求过滤。它足以支持的判断更窄,却更实用:判断凭证隔离,不能只统计一种载体是否消失;要追踪同一秘密的所有出口,以及接收方最终获得的集合。

English · 实验方法、固定版本与逐轮结果

Last updated: