2026年8月28日 2 分钟阅读

不想把源码和密钥直接交给云端 Agent?Cover 的双向隐私代理实战

tinyash 0 条评论

当 Codex、Claude Code 或 Cursor 需要读取真实项目时,真正棘手的往往不是模型能力,而是请求里混着不该离开电脑的内容:内网地址、客户名称、数据库密码、云平台令牌,以及带有上下文关系的配置文件。只做字符串打码会破坏上下文,完全拒绝发送又会让 Agent 无法工作。

Cover 的思路是把代理放在本机:请求离开电脑前,先把命中的敏感值替换成稳定、看起来合理的伪值;模型返回响应后,再把伪值还原成原值。这样模型看到的仍是一套自洽的环境,Agent 生成的命令和工具调用也能继续使用真实值。它是一个用 Go 编写的 Apache-2.0 项目,官方 README 明确列出的客户端包括 Codex、Claude Code、Cursor、Pi/Oh My Pi,以及兼容 OpenAI 或 Anthropic 的 SDK 和路由器。

先理解它保护的是什么

Cover 不是把所有请求都变成不可逆的 [REDACTED]。它提供六种策略:allow 原样放行,placeholder 替换成短令牌,pseudonymize 生成稳定的拟真值,mask 只保留首尾字符,redact 做单向删除,block 则在本地直接拒绝请求。

需要模型在多轮对话中保持同一身份时,适合使用 pseudonymize。例如同一个内网地址在三次请求中都变成同一个假地址,模型才能理解“这还是那台服务”。如果内容本身绝不能被推断,或者不需要在响应中恢复,就应该选择 redactblock,而不是误把可逆替换当成绝对隔离。

稳定性来自两部分:安装时生成的密钥通过 HMAC-SHA-256 为原值派生确定性伪名;真正用于恢复的映射只保存在进程内存中,并按会话隔离、设置 TTL 和容量上限。密钥本身不能反推出原值,但如果团队需要跨重启维持同一组伪名,就必须像保护其他本地密钥一样保护 pseudonym.key

安装与第一次自检

官方安装器会根据操作系统和 CPU 下载发布包,校验公开的 SHA-256 checksums,再原子安装到 ~/.local/bin/cover。不需要 Go 工具链,也不需要先 clone 仓库:

curl -fsSL https://raw.githubusercontent.com/DavidCarliez/cover/main/scripts/install.sh | bash

安装器还支持非交互配置。例如只配置 OpenAI 和 Claude 客户端,可以把环境变量传给执行安装脚本的 Bash 进程:

curl -fsSL https://raw.githubusercontent.com/DavidCarliez/cover/main/scripts/install.sh | \
  COVER_AGENTS=openai,claude bash

首次初始化、启动和本地回环测试如下:

cover init
cover start --detach
cover doctor
cover test
cover monitor

cover test 的价值在于它不调用网络,而是在本地完成一次脱敏与恢复往返。cover doctor 则会检查配置、监听器、伪名密钥、守护进程、路由、失败关闭行为,以及 Codex 请求压缩等项目。部署到团队机器前,先让这两个命令通过,比直接拿真实 API 密钥做一次试运行更稳妥。

用规则把“该替换什么”写清楚

规则位于 ~/.config/cover/config.yamlrules 节。选择器可以是 JSON 键、正则表达式或内置检测器。下面的配置只把密码字段做可逆伪名处理,同时遇到形如 API key 的值就在本地阻断:

rules:
  password_fields:
    keys: [password, passwd, pwd, passphrase, user_password, database_password]
    category: password
    action: pseudonymize
    generator: password
    priority: 220
  forbidden_api_key:
    pattern: '(?i)api[_-]?key\s*[:=]\s*(?P[A-Za-z0-9._-]{16,})'
    action: block
    priority: 100

这里有两个容易被忽略的工程细节。第一,按键匹配会保护完整的字符串值,避免把普通用户名误判成密码;正则中的命名捕获组 (?P...) 让规则只替换匹配到的值,而不是改写整段文本。第二,规则、动作、生成器和捕获组都会在启动时校验。表达式有误、映射耗尽、请求 JSON 损坏或超过大小限制时,Cover 不会退回“原样转发”,而是拒绝处理,这才符合隐私代理的失败关闭语义。

项目内置的检测器覆盖多类云平台和协作平台令牌、私钥块、JWT、邮箱、身份证明、银行卡、电话号码等。对于项目代号、人名或地址这类自由文本,可以选择启用本地 llama.cpp 检测器;但它是可选的额外层,不应把“启用了本地模型”理解成所有内容都能被识别。

接入 Codex 时的关键边界

Cover 默认只监听 127.0.0.1:8317,上游地址则指向真正的模型服务或路由器。Codex 使用 Responses API,因此官方示例要求在 ~/.codex/config.toml 中配置一个本地 provider,并关闭请求压缩:

model_provider = "cover"

[model_providers.cover]
name = "Cover"
base_url = "http://127.0.0.1:8317"
wire_api = "responses"
requires_openai_auth = true
supports_websockets = false

[features]
enable_request_compression = false

关闭压缩不是性能偏好,而是可检查性的前提:代理需要读取请求体,才能对 JSON 字段做规则匹配。与此同时,Cover 不改写认证 header,因此上游服务仍然能使用原有的鉴权方式。若接的是路由器,应把 Cover 的 upstream 指向实际路由地址,并根据路由器的认证方式使用对应的环境变量配置。

配置完成后,建议把验证拆成三个层次。第一层只测规则:用 cover test 确认替换和恢复逻辑闭环;第二层用 cover inspect request.json 检查真实业务 JSON 中哪些字段会被命中;第三层才让一个低权限测试账号访问模型。这样能区分“规则没有匹配到”“代理没有接管客户端”和“上游本身拒绝请求”三类问题。若直接把生产凭据和生产配置拿来试,排错时很容易把数据泄露误认为普通路由故障。

对于多轮 Agent 会话,必须明确会话边界。Cover 支持通过 X-Cover-Session 发送稳定会话标识,让同一会话的映射在多个请求之间继续存在;没有这个 header 的请求则使用隔离、请求级映射,并在请求结束后删除。前者适合需要跨轮次追踪同一主机或客户的编码任务,后者更适合一次性的文档总结。团队可以在测试中主动重启代理、切换会话并检查伪名是否变化,把 TTL、容量上限和密钥备份策略写进运维文档,而不是依赖默认行为。

配置完成后,可以先准备一个只含测试数据的 request.json,用下面的命令检查代理究竟会转发什么:

cover inspect request.json
cover inspect request.json --session demo

inspect 不会访问模型服务,会展示转换后的请求、命中的规则、类别、动作和阻断状态,但不会打印可逆映射。平时用 cover monitor 只查看时间、状态码、转换次数、字节数、延迟和类别等元数据;只有在受控的本地终端中,才临时使用 cover monitor --show-content 排查具体转换。这个选项会显示原值和伪值,不能用于共享终端、录屏、CI 日志或支持工单。

它不能替代完整的出站数据治理

Cover 的优势是保护结构化请求,同时尽量不破坏 Agent 的工作流,但边界也写得很清楚。它不检查图片像素,图片数据、图片 URL 和文件 ID 默认会直接通过;如果截图同样敏感,应把媒体策略设为 block,或在进入代理前自行清理。它也不负责绕过代理的流量,无法保证所有应用都自动进入这条链路。

此外,认证 header 默认不被重写,URL 查询参数和路径也必须纳入自己的威胁建模。对于必须保持真实值才能工作的工具调用,应该优先使用可逆伪名,并通过会话 header 维持映射;对不需要恢复的遥测、日志或示例文本,则使用单向 redact。不要在 --show-content 模式下做生产排障,也不要把 pseudonym.key 提交进仓库。

如果你的团队已经要求所有编码 Agent 经过一个本地出口,Cover 是一个相对清晰的补强层:它把敏感数据处理前移到请求离开主机之前,用规则、审计元数据和失败关闭减少误传概率,同时保留模型完成任务所需的上下文。它不是 DLP、权限系统或网络隔离的替代品;真正可靠的组合应当是最小权限、独立凭据、出站控制,再加上对代理规则的持续测试。

相关链接

发表评论

你的邮箱地址不会被公开,带 * 的为必填项。