关于 secret
secret 是面向编码 Agent 的本地密钥处理 CLI、仅提供名称信息的 MCP 服务和防护钩子。它允许 Agent 为子进程选择凭据而不暴露其值,并可从命令输出中脱敏已加载的值;其防护用于减少意外泄露,并非沙箱。
主要功能
- 01仅显示密钥元数据
- 02使用选定密钥运行命令
- 03脱敏命令输出中的密钥值
- 04阻止高风险密钥读取的钩子
- 05指导 Agent 使用的技能
适用场景
- 01使用选定凭据运行部署命令
- 02让 Agent 查看可用密钥名称而不读取值
- 03减少 Agent 使用 Shell 时意外泄露密钥
MCP 相关
其可选的本地 stdio MCP 服务可列出、显示、比较经明确批准的存储,并检查其状态。它只提供元数据,不返回密钥值。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
secret
让编码 Agent 使用你的凭据,而无需读取凭据。
有权使用 shell 的 Agent 可以运行 cat .env、运行 printenv,或从配置文件中 grep 出令牌;这些值会进入它的上下文、日志,甚至服务提供商的服务器。secret 为 Agent 提供了经过认可的替代方式:它只能看到键名和掩码后的长度,选择命令所需的键,而值会直接传入该子进程的环境变量。
三个部分,可搭配使用,也可单独使用:
| 部分 | 功能 |
|---|---|
bin/secret | CLI。解析 KEY=VALUE 存储(绝不执行其内容),显示已掩码的名称,使用选定的键运行子进程,并从子进程的 stdout 和 stderr 中删去所有已加载的值。 |
hooks/guard-secrets | Claude Code 和 Codex 的 PreToolUse hook。禁止读取存储文件、转储环境变量、使用凭据打印工具(gh auth token、security -w、pbpaste 等),以及会打印存储内容的搜索操作。 |
skills/secrets/SKILL.md | 告诉 Agent 如何使用 CLI,以及在不向聊天询问值的情况下,如何从 guard 拒绝中恢复。 |
本工具不是什么
用于预防意外,而非沙箱。 它可以防止 Agent 因习惯或误操作而读取密钥,但无法阻止有 shell 权限的蓄意或已遭入侵的 Agent:经过转换的输出(base64、URL 编码、子串)不会被删去;guard 无法解析的 shell 间接操作会被允许,除非其中指名了受保护的文件或操作;MCP 搜索工具不在覆盖范围内;如果输入格式错误,guard 不会作出判断(没有 jq 时,它会拒绝所有请求)。应将其视为一层防护,而非安全边界。
安装
自选安装 Go 命令行工具和仅显示名称的 MCP
规范安装说明涵盖安装、经批准的存储引用、各客户端注册、验证、更新和移除。v0.3.2 版本正在准备中;这些固定版本命令需要使用已发布的资源,绝不会选择最新版本或回退到其他版本。
前置条件:已通过身份验证的 GitHub CLI gh,以及 Unix 上的 curl 和 Python 3,或 Windows 上的 curl.exe。请通过可信渠道安装工具。请在私密终端中自行运行 gh auth login,或通过可信的凭据环境提供 GH_TOKEN,且不要显示该令牌。切勿将令牌粘贴到聊天或客户端配置中。
sh -c 'umask 077; d=$(mktemp -d) || exit
curl -fsSL https://raw.githubusercontent.com/avhn/secret/v0.3.2/install.sh -o "$d/install.sh" && sh "$d/install.sh" "$@"
status=$?; rm -rf "$d"; exit "$status"' sh
Windows PowerShell:
& { $ErrorActionPreference = 'Stop'; $d = Join-Path ([IO.Path]::GetTempPath()) ([guid]::NewGuid().ToString('N')); New-Item -ItemType Directory -Path $d | Out-Null
try { irm https://raw.githubusercontent.com/avhn/secret/v0.3.2/install.ps1 -OutFile "$d\install.ps1" -ErrorAction Stop; & (Get-Process -Id $PID).Path -NoProfile -ExecutionPolicy Bypass -File "$d\install.ps1" @args; $status = $LASTEXITCODE }
finally { Remove-Item -LiteralPath $d -Recurse -Force }; exit $status }
这些先下载再运行的代码片段只有在下载成功后才会运行,并会在清理后保留失败状态。请在最后一个 sh 或 PowerShell 闭合大括号之后添加安装程序标志;详情请参阅安装说明。PowerShell 会使用 -NoProfile -ExecutionPolicy Bypass 在同一主机的子进程中运行该文件,并在清理后传递其退出代码。此绕过仅适用于该子进程,不会改变任何持久策略;集中强制执行的组策略仍可能优先生效。
如果安装程序报告
secret: GitHub CLI is not authenticated; run gh auth login or set GH_TOKEN, then retry,
请在私密环境中验证 gh 身份,或修正其可信环境,然后重试;不要粘贴或打印令牌。
引导过程信任 GitHub HTTPS、仓库和标签治理,以及通过审核的安装程序,然后再进行验证。两者都需要 gh,并会验证发布证明,而非仅验证校验和;SECRET_RELEASE_COMMIT 可选地固定到经独立身份验证的完整提交 C。Unix 还需要 curl 和 Python 3;Windows 需要 curl.exe。先下载并审核后再运行,或使用可信检出版本,可提供更强的引导审核保障。安装程序仅发布 secret-go / secret-go.exe,并打印绝对路径。Unix 不会修改 PATH;Windows 只会将其所在目录添加到用户 PATH。两者都不会注册 MCP、读取存储或激活钩子。原始可执行文件不具备检出启动器的逐次执行重新哈希功能。
粘贴给你的 Agent:请按照 https://github.com/avhn/secret/blob/v0.3.2/docs/setup.md 安装并注册 secret MCP;向我索取准确的存储引用,绝不要发现或读取存储、处理值或绕过保护机制。
| 表面 | 支持情况和依据 |
|---|---|
| Go 命令行工具 | v0.3.2 面向 Linux、macOS 和 Windows amd64/arm64;仍需满足新的原生候选版本/公开安装门槛。v0.2.3 的 Linux/macOS 发布已完成。 |
| 本地 stdio MCP | 自选启用 mcp --store STORE_REFERENCE;仅限 list/show/diff/health,不显示值。元数据仍可能暴露名称、标签、路径和账号 ID。 |
| 桌面捆绑包 | secret-v0.3.2-desktop.mcpb:macOS 通用版和 Windows amd64 版;通过锁定命令行工具的原生冒烟验证,不等同于在主机上测试过的桌面安装。 |
| Registry | 名称 io.github.avhn/secret;发布需单独经过所有者批准,此处不声称已发布。 |
| 插件和钩子 | 四个清单均为 0.3.2;已安装的钩子仍是 Bash 保护机制。M4.1 Go 激活正在等待赞助,且不声称主机具有故障时默认拒绝的保障。 |
请参阅安装和回滚,了解版本固定、依赖项、离线选项和故障恢复,以及发布审批。
Bash CLI、保护机制和技能(默认安装)
要求:bash 3.2 或更高版本(macOS 自带的 bash 可用)、perl,以及保护机制所需的 jq。这些仍与选择启用的 Go 可执行文件和 MCP 注册分开。
CLI:
git clone https://github.com/avhn/secret ~/.local/share/secret
ln -s ~/.local/share/secret/bin/secret ~/.local/bin/secret
作为 Claude Code 插件的保护机制和技能:
/plugin marketplace add avhn/secret
/plugin install secret@secret
对于 Codex CLI,请从此仓库的 Codex marketplace 安装插件。
插件包含保护机制和技能,不会修改 ~/.codex/hooks.json:
codex plugin marketplace add avhn/secret
codex plugin add secret@secret
在 Codex 中,打开 /hooks,并信任已安装的 secret hook 后再使用。
未受信任的 hooks 会列出,但不会运行;hook 发生变化时,请检查并重新信任。
/plugins 可用于检查已安装的插件。该插件不会将 bin/secret 加入 PATH。如果要使用 CLI,请单独安装(该符号链接要求将 ~/.local/bin 加入 PATH):
mkdir -p ~/.local/bin
# If you have not already cloned the repo in the CLI step above:
git clone https://github.com/avhn/secret ~/.local/share/secret
ln -s ~/.local/share/secret/bin/secret ~/.local/bin/secret
如果你的 Codex 版本不支持插件 marketplace,请从仓库检出代码并手动安装。复制 hook 模板,使用绝对命令路径,并将技能安装到用户技能根目录:
mkdir -p ~/.codex ~/.codex/skills
jq --arg command "$HOME/.local/share/secret/hooks/guard-secrets" \
'.hooks.PreToolUse[].hooks[].command = $command' \
~/.local/share/secret/codex/hooks.json >~/.codex/hooks.json
ln -s ~/.local/share/secret/skills/secrets ~/.codex/skills/secrets
如果 ~/.codex/hooks.json 已存在,请合并其中的 PreToolUse 组,而不要替换整个文件。Codex 也接受 config.toml 中内联的 [hooks];此处使用 hooks.json 片段,以便复制时无需更改该文件。
也请打开 /hooks,信任手动安装的 hook。Codex 会将 shell 命令作为 Bash hook 名称发送,并将补丁作为 apply_patch 发送。保护机制要求 hook 的 PATH 中包含 jq 和 perl。
保护机制允许使用普通的 rg,因为 ripgrep 可以设置为跳过存储文件。安装保护配置,或将其中的 glob 合并到你自己的配置中:
mkdir -p ~/.config/ripgrep
cp ~/.local/share/secret/examples/ripgreprc ~/.config/ripgrep/config
export RIPGREP_CONFIG_PATH="$HOME/.config/ripgrep/config" # in your shell profile
在暂存的 Go CLI 中选择启用 age 存储
M5d 在 Linux/macOS 上新增显式的 age:NAME 加密文件存储,使用经过审查的 filippo.io/age v1.3.2,支持经过整体存储认证的读取,以及仅写入密文的原子操作。age-init 仅创建新项,age-rekey 会在发布前验证新身份;两者都要求使用真实终端并精确确认目标。密钥文件必须位于 HOME/.secrets/.age-keys/ 下,且权限必须为私有;会读取值的命令必须显式指定 --age-identity FILE。仅涉及名称的接口无需身份,但其外层元数据未经认证。使用 list --backend age;默认发现方式和 Bash CLI 均未更改。虽然 M5a 的独立 Windows CLI 门禁已通过,但 Windows 上的 age 文件系统操作仍不受支持。请参阅 age 设置、迁移、恢复和限制。M5d 已通过 PR #28 中的托管门禁;这不会启用 hooks,也不代表已授权发布。
用法
存储使用 KEY=VALUE 行:默认使用 ~/.secrets.env 和 ~/.secrets/*.secret
(可通过 SECRETS_ENV 和 SECRETS_DIR 覆盖)。精确的分节标题(如
[env=dev,region=eu])会限定其后赋值的作用范围;[] 会重置为无标签。
其他方括号行会被忽略。标签使用标识符名称,值由字母、数字、下划线、
点或连字符组成(首字符必须是字母、数字或下划线)。带标签的文件不再是
其他工具可用的普通 dotenv 文件。较旧版本的 secret 会将所有分节读取为
一个扁平存储,因此请先升级,再引入标题。
secret list # store paths, never contents
secret show ~/.secrets.env # API_TOKEN=<40 bytes>
secret stash ~/.secrets.env API_TOKEN # hidden prompt, atomic write
secret run -f ~/.secrets.env --key API_TOKEN -- ./deploy.sh
secret show --env dev ~/.secrets.env # selected masked keys and unset keys
secret stash --env dev ~/.secrets.env API_TOKEN
secret run -f ~/.secrets.env --env dev --key API_TOKEN -- ./deploy.sh
显式的 keychain:NAME 和 libsecret:NAME 引用使用密钥库存储;
file:PATH 强制使用字面文件路径,包括看起来像后端引用的路径。
裸名称和路径仍使用文件存储。密钥库名称只能包含字母、数字、下划线、
点和连字符(且必须以字母、数字或下划线开头)。每个密钥库存储都有一个
私有的、以原子方式写入的 ~/.secrets/NAME.keys 清单,其中仅包含键名、
规范标签和随机账户标识符,绝不包含值。list 和 show 仅使用清单;
show 会显示 <stored>,而不是字节数。run 和 exec 会在选择键之前
加载所有已注册项,因此查找失败会阻止子进程启动,而 run 可能会从未选中
的环境中对值进行隐藏。get 和 clip 只会获取选中的项。后端写入成功后,
若清单发布失败,可能会留下未注册的密钥库项。
在 Linux 上,libsecret:NAME 使用 secret-tool 和已解锁的 Secret Service
会话。值通过 stdin 发送给提供程序,并读取到私有文件中。Stash 接受末尾
没有换行符或有一个末尾换行符的值(会移除该换行符)。空值、包含换行符或
CR 的值、NUL、首尾空白以及带引号的值都会被拒绝。
在 macOS 上,keychain:NAME 使用用户的默认 Keychain,或显式指定的
SECRET_KEYCHAIN 绝对 Keychain 路径(仅允许字母、数字、_、.、/
和 -;需要引号的路径会被拒绝)。值会被十六进制编码后写入 security -i
stdin 命令,绝不会放入进程参数中。Keychain stash 接受不含 Unicode 控制字符
或行分隔符的可打印 UTF-8 文本;不符合此子集的值会被拒绝,因为 security -w
是文本接口。发布清单前,必须先通过私有文件读回并确认内容一致。读取时会
准确移除 security -w 添加的一个换行符。测试桩仍可用于隔离测试;
切勿将其用于真实凭据。
--env dev 等同于 --label env=dev;重复使用 --label name=value 可选择
多个标签。不指定选择器时,只会匹配无标签记录。对于每个键,匹配的标签集
中最具体的优先;若有多个同样具体且不同的匹配项,则会因歧义而失败。
不指定选择器的 show 会列出每条记录,显示规范化排序后的标签和经过掩码的长度。
stash 只更新标签集完全相同的记录,而 get 和 clip 会选择与 run 相同的记录。
run 只会导出选中的键(必须指定 --key,--optional-key 可选;不指定
选择器时会导出所有键),并会将子进程输出中所有已加载的值替换为 <redacted>。
建议通过 stdin 传递值,因为子进程若将值放入自己的 argv,就会使其暴露在进程列表中:
secret run -f ~/.secrets.env --key API_TOKEN -- bash -c \
'printf "Authorization: Bearer %s\n" "$API_TOKEN" | curl -fsS -H @- https://api.example.test'
仅供人工使用、守卫会禁止 Agent 使用的命令:
secret get FILE KEY会输出一个值,且只会输出到终端。secret exec ...是不进行隐藏的run,适用于需要字节精确 stdio 的交互式工具和 MCP 服务启动器。
secret clip FILE KEY [SECONDS] 会复制一个值,并在 45 秒后清空剪贴板,除非你在此期间复制了其他内容。
该值不会出现在 Agent 的输出中,因此守卫允许此命令;技能会告知 Agent 仅在你要求使用剪贴板时才使用它,而读取剪贴板内容则会被禁止。
运行 secret help 查看完整参考,包括退出状态。
分阶段 Go 操作员工作流(M3)
M3 已通过托管式 CI 门禁(PR #8)。这些命令已在 Go
CLI 中实现,而已发布的 bin/secret 仍是 Bash;这并非 CLI 或插件的切换。运行
go build -o /absolute/private/build/secret-go ./cmd/secret 来试用分阶段推出的 CLI。
以下示例使用 secret-go 代表该二进制文件,并使用占位存储路径。
请在自己的终端中直接调用操作员,切勿通过 Agent 工具调用。
secret-go import --from dotenv:/absolute/source.env --into file:/absolute/team.secret
secret-go import --from op:OPAQUE_ID --into file:/absolute/team.secret --map password=API_TOKEN
secret-go export --from file:/absolute/team.secret --to libsecret:team --on-conflict=fail
secret-go rotate file:/absolute/team.secret API_TOKEN --env prod
secret-go rename file:/absolute/team.secret API_TOKEN SERVICE_TOKEN --env prod
secret-go delete file:/absolute/team.secret SERVICE_TOKEN --env prod
secret-go show --format=json file:/absolute/team.secret
secret-go diff --format=json --env dev --env prod file:/absolute/team.secret
secret-go doctor --format=json libsecret:team
操作员在访问存储前要求 stdin 和 stdout 均连接到终端,随后须在控制终端上对每个目标/键/标签身份进行精确的隐藏确认。
不支持 --yes、管道式确认或操作员 JSON。轮换时会以隐藏方式读取新值,绝不会将其放在 argv 中。生命周期标签用于标识确切记录。引用必须显式采用 file:ABS_PATH、keychain:NAME 或 libsecret:NAME。导入/导出仅插入;op/bw 导入需要显式字段映射。导出需要使用 --on-conflict=fail、指定不同的已实现密钥库目标,并为带标签的记录指定显式选择器;若不指定选择器,则仅符合未带标签的记录。
--dry-run 仅列出名称/冲突,且仍要求连接真实终端。
Doctor 会报告已跟踪的恢复候选项和手动验证指南,而非已证实或完整的历史孤立项清单,也不会报告已安装主机的可信状态。
私有模板使用字面量 {{KEY}} 占位符,且仅使用选定的键:
secret-go run -f file:/absolute/team.secret --key API_TOKEN \
--template-file /absolute/client.template -- ./consumer
子进程通过 SECRET_TEMPLATE_FILE 接收渲染后的路径,绝不会在 argv 中接收文件内容。输出仍会遮盖所有已加载的字面值。文件存放在固定路径 HOME/.secrets/.rendered/<random>/payload 下,不受 SECRETS_DIR 影响;目录权限为 0700,payload 权限为 0600。不存在/未选定的占位符、不安全的别名、exec 和输出目录选项均会被拒绝。监督进程会在正常退出、错误或可捕获信号触发的清理前停止其进程组。SIGKILL、崩溃或断电可能会留下受保护的明文;清理只是尽力而为,并非安全擦除。
list/show --format=json、diff、doctor、completion 和审计查询仅公开元数据,绝不公开值、哈希或长度。元数据可能会泄露键名、标签、后端类型、存储路径和提供商账户 ID。旧版文本 show 仍会显示经过掩码处理的字节长度和排序结果。Completion 会输出字面量候选项,而非 shell 代码,并且只读取显式指定的 -f 作用域。除非操作员收到 --audit-dir ABS_PATH,否则审计处于关闭状态;可使用 audit --directory ABS_PATH --format=json 查询。仅包含名称的事件会在四个私有文件间轮换,每个文件上限为 1 MiB,权限均为 0600。
MCP 默认关闭,除非显式列入允许列表,例如
secret-go mcp --store file:/absolute/team.secret --store libsecret:team。
stdio 服务仅开放 list/show/diff/health,不会公开值或支持修改;
请求无法扩展该精确允许列表。配置此服务会允许上述路径和账户元数据传递给其客户端。不会启用网络监听器或自动发现环境中的存储。未更改的已安装钩子会保守地拒绝新子命令,包括仅包含名称的子命令;此功能不会为 Agent 授予钩子豁免。M5a 的原生 Windows CLI、控制台、存储、Job 和 Credential
Manager 门禁已通过;Windows 支持说明了其限制以及仍待提供的单独发布资源证据。此处不声称提供任何已安装主机保护。有关门禁的信息,请参阅 CONTRIBUTING.md;有关实现约定,请参阅 M3 计划。
测试
bash tests/test-secret.sh # CLI matrix, needs perl, python3 and rg
bash tests/test-backends.sh # disposable keystore stub matrix
bash tests/test-guard.sh # guard matrix, needs jq
测试套件仅使用临时目录和合成值。CI 会在 Linux 和 macOS 上运行测试,包括原版 /bin/bash 3.2。
开发
Go 重写工作正在进行;请在 ROADMAP.md 中跟踪里程碑。 有关环境设置和 PR 指引,请参阅 CONTRIBUTING.md;有关编码 Agent 规则,请参阅 AGENTS.md。
许可证
GPL-3.0-or-later,版权所有 Mert Dede。
1Password 脚手架(未启用)
暂存的 Go 实现包含仅用于测试的只读 1Password 脚手架。 默认情况下,注册、发现和读取功能均处于禁用状态,等待独立的提供方证据和许可证审查。没有可启用这些功能的环境开关。 Bash CLI、已安装的钩子和插件清单均未更改。请参阅契约和限制;不要让 Bash CLI 指向 Go v2 清单。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。