secretgate —— 面向编码智能体的本地密钥防火墙
凭证绝不应流入大语言模型 API。secretgate 在本地强制执行此项保护,
采用确定性引擎(node scripts/secretgate.mjs,无需 npm 安装,无需
密钥):基于 gitleaks 转换的 221 条规则 + 熵门限 + Luhn 校验的卡号。
在智能体钩子 API 支持改写的地方,密钥会被编辑为稳定占位符,
并在智能体写回时被本地还原(编辑-还原模式);在仅支持拦截的地方
(Claude Code/Codex 上的提示),相应提示会被拦截并提供编辑后的副本以供重新发送。
激活 → 安装(技能触发时首先执行此操作)
当此技能激活(用户要求保护密钥 / 安装 secretgate / 设置防火墙)时,先运行诊断程序, 再连接尚未连接的组件。secretgate 是一个技能,而非 npm 包 —— 您需运行其自带捆绑:
node scripts/secretgate.mjs status # 当前已连接的内容
node scripts/secretgate.mjs install --claude-code # 钩子 + permissions.deny 写入 ~/.claude/settings.json
node scripts/secretgate.mjs install --codex # ~/.codex/hooks.json + [features] hooks = true
node scripts/secretgate.mjs install --opencode # 自包含插件,位于 ~/.config/opencode/plugin/
node scripts/secretgate.mjs install --all # 全部三者
--project 将 Claude Code 安装限定到 ./.claude/settings.json。
install 会将捆绑的副本固定到 ~/.secretgate/bin/ 下,并让智能体调用该副本,
因此在技能缓存被清除后它仍能正常工作。务必告知用户之后重启智能体会话 ——
钩子在启动时加载。连接完成后,编辑过程自动且确定性地进行(由钩子执行,而非您)。
命令
| 命令 | 功能 |
|---|---|
status | 诊断:逐个智能体的连接情况、引擎、保险库健康状态、限制 |
| `scan <文件 | 目录 |
pipe | 从 stdin 到 stdout,密钥被编辑为占位符 |
allow <值> / allow --rule <规则ID> / allow --path <glob> | 白名单(值存储为 SHA-256,从不明文存储) |
vault list / vault clear | 检查占位符映射(绝不显示密钥) |
uninstall --<智能体> | 精确移除安装时添加的内容 |
保护原理(用户问及时告知)
- 提示:Claude Code/Codex → 被拦截并提供编辑后的副本(可添加
[allow-secret]一次性绕过)。OpenCode → 在原位静默编辑。 - 文件读取:
.env*、密钥、~/.aws、~/.ssh……被直接拒绝 (.env.example/.sample/.template仍可读取)。值绝不会进入模型。 - 工具/bash 输出:被编辑为
SECRETGATE_<哈希>占位符 (Claude Code + OpenCode;Codex 尚不能改写输出)。 - 还原:当智能体将占位符写入文件时(Write/Edit),磁盘上会写入真实值。
Bash 还原默认关闭(防范提示注入窃取)——在
~/.secretgate/config.json中 设置restoreBash: true来启用。 - 干净的工具调用:Claude Code 的预工具使用钩子返回最小 JSON
(
{},无决策 = 正常权限流程),而非空 stdout。 空的钩子输出会触发 Claude Code 的一个 bug(anthropics/claude-code#77782), 导致即使处于自动模式,每次匹配的工具调用都会强制弹出交互式权限提示 —— 而 Claude Code <= 2.1.212 会拒绝文档中记录的"defer"决策值, 因此{}是普遍适用的弃权方式。
未覆盖的内容(如实告知用户)
- Claude Code 的
@file内联引用内容不会触发工具钩子 (只有 permissions.deny 规则能覆盖该场景)。 - Codex 非交互式运行(
codex exec)——上游 bug,钩子不触发。 - 图片/截图/剪贴板、MCP 工具流量,以及安装前已在对话中的内容。
- 若钩子进程被杀死或超时,智能体会继续执行(智能体侧故障开放); secretgate 自身对于预事件中的错误则采用故障关闭模式。
- 被拦截的提示会在本地由 Claude Code 回显(终端中显示
Original prompt:,claude -p的 JSONresult中也有)——API 永远看不到它, 但请将管道化的无头输出视为敏感信息。
误报处理
优先采用最窄的修复方式:在行内添加 # pragma: allowlist secret(或
gitleaks:allow)→ allow <值>(哈希化)→ allow --path <glob> → allow --rule <规则ID>(最后手段)。项目可以在 .secretgate.json 中提交额外的白名单条目
({"allowlist": {"paths": […]}})。