脱敏密钥
在机密到达模型之前完成脱敏
Tokenhush 是一个本地、仅回环的 HTTP 网关:位于 AI 编程工具与模型提供商之间。外发方向,它遍历声明为 JSON 的请求体,把检测到的密钥或 PII 替换成可还原的会话级占位符,再转发改写后的请求体;回程方向,它先整段缓冲响应,并在你的工具收到之前还原原值。想在发送给 LLM 之前脱敏密钥、又不想在机器上信任一张全局证书时,这就是可用的检查点。
仅绑定本机回环、不做 MITM、不装根证书;密钥与占位符的映射仅保留在内存中,限定于本次会话。
问题:密钥与 PII 同时外发
AI 编程工具用仓库上下文组织请求。.env 文件里的密钥、配置文件里的令牌、粘贴进提示词的凭据,对工具来说都不是特例:它们只是文本,会随请求体一起发出。
文件级卫生在请求形成之前就已经生效:.gitignore 让文件不进 git,厂商开关减少服务端保留的内容——但两者都不在发送时运行,而请求一旦发出就无法撤回。发送时脱敏是另一个检查点:请求体在工具组织完成之后、提供商收到之前被改写。回环网关就位于这个位置,这也是它与对比页里其他做法在脱敏视角上的关键区别。
面向 LLM 请求的 PII 脱敏同理:通过 Luhn 校验的卡号、以已知公共后缀结尾的地址,会被同一次确定性遍历命中并替换为占位符,提供商收到的是请求的形态,而不是具体的值。
外发脱敏,回程还原
把工具指向本机回环网关(127.0.0.1:8787),而不是厂商端点。一次请求、两个方向,只有其中一个方向会改写:替换发生在请求路径上,原值只在响应路径上还原。
外发请求
工具把请求指向本机回环
请求体先到达网关,再有任何厂商端点看到它。这里没有流量拦截:工具被配置为直接访问回环地址。
网关遍历请求体并写入占位符
完整读取声明为 JSON 的请求体,运行已启用的检测器;每个命中变成会话级占位符,例如
__PII_api_key_ae9c0b46a8f3__,改写发生在转发之前。提供商收到占位符而不是原值
上游看到的是占位符,而不是它们所代表的值。没有被任何检测器标记的值仍按工具写下的原样发出——这正是检测器质量构成工具诚实边界的原因。
入站响应
响应先整段缓冲
先记录状态码与响应头,再把响应体(含
text/event-stream)完整缓冲并解码;此时还没有提交任何字节。占位符回填为原值
本次会话铸造的占位符被换回原值;不是本次会话铸造的外部占位符按原样返回,而不是被猜测成某个机密。
原值回到工具
回填最后运行,响应一次提交,因此客户端不会拿到半截、网关却无法收回的响应。
占位符在出站方向永不回填。只有客户端拿到原值。
回填只有一个方向:返回客户端的响应路径。出站写入方只持有正向映射——没有反向映射,也没有还原方法——因此出现在新的外发请求体里的占位符依然只是占位符。
脱敏对照:四种做法
下面每种做法都能减少离开机器的内容;区别在于减少发生在什么时刻,以及仍带着密钥的请求会经过哪里。
| 做法 | 对请求中的密钥做什么 | 运行位置 |
|---|---|---|
| 依赖 .gitignore 与厂商开关 | 发送时不运行任何检查:记得排除的文件不进 git,忘了排除的文件里的密钥照样随请求外发。 | 文件级卫生,在请求被组织出来之前生效。 |
| 关掉发送过多的功能 | 离开机器的字节更少,但对已经进入请求体的密钥无能为力。 | 厂商侧设置,按提供商生效,而不是按请求生效。 |
| 带根证书的本机 MITM 代理 | 机器上任何客户端都能被检查与改写,包括没有 base URL 设置的客户端;它要终止 TLS,于是根证书要在全机器范围被信任。 | 系统级:位于每个客户端与每个端点之间。 |
| Tokenhush | 声明为 JSON 的请求体被遍历,每个命中在转发前变成会话级占位符;不终止 TLS、不装根证书,映射只保留在内存中。 | 仅本机回环:在你能指向 base URL 的那些工具的请求路径上,只有一个检查点。 |
检测器偏向精度:未被任何检测器标记的值仍会外发。公开口径是高置信拦截加全程可审计,而不是「什么都不会外泄」的保证。
脱敏不做哪些事
在机密到达模型之前完成脱敏,不等于「防止一切形式的机密外泄」。这些边界随设计而来,写在文档里,而不是留到使用中才发现。
编码后的密钥不会被捕获
外发前经过 base64、hex 或 URL 编码的密钥不会被检测到:改写过程没有归一化环节。JSON 字符串转义在两个方向都被处理;非 identity 的请求 Content-Encoding 会以 415 拒绝,而不是解码后再检测。
响应方向不做脱敏
响应侧规则只能 allow、warn 或 block;替换只属于请求路径,任何试图对响应脱敏的规则在编译时即被拒绝。
不扫描 JSON 的对象键
只遍历值,因此把密钥用作对象键时会原样转发。
完整边界清单与随之而来的残余风险都记录在安全模型中。覆盖范围恰好是你能指向 base URL 的工具;无视 base URL 的客户端需要另一套拦截设计。
用本地 echo 上游验证脱敏
验证指南用本地 echo 上游证明整个往返:上游把收到的请求体原样回显。上游终端显示的是占位符;网关的 stderr 每次脱敏打印一行掩码输出、每次还原打印一次计数;客户端拿回原值。
- 上游看不到原值echo 上游就是模型的替身:它打印收到的请求体——那是占位符,不是密钥。
- 日志只含元数据脱敏行只有类型、长度与掩码形态;还原行只有计数。
- 元数据可查询tokenhush status --json 会报告 redactions 这类计数,机器可以复核人刚看过的同一次往返。
tokenhush run
# point a tool at http://127.0.0.1:8787
tokenhush status --json这些都写在文档里
请求与响应两条路径、检测器契约,以及仍然存在的风险,都来自公开文档。