# 安全与合规 ## 信任边界 本项目**只在本机回环地址上工作**: ``` 127.0.0.1:8790 桥(OpenAI 兼容接口) 127.0.0.1:8792 控制台(管理界面) ``` 两者都不接受外部连接。项目中没有、也不应有任何把监听地址改为 `0.0.0.0` 的配置项 (`.env.example` 与代码注释中均明确标注了这一点,因为那会把你账号的模型额度 暴露给能访问该端口的任何机器)。 --- ## 明确不做的事 | 不做 | 原因 | |---|---| | **不内置任何密钥** | AtRest 字段密钥每次从写入登录文件的那个客户端现取;项目内不存在密钥副本 | | **不落盘令牌** | 令牌只在内存中解密后用于构造请求头,不写文件、不写日志 | | **不写回登录文件** | 登录文件是客户端的加密存储,写入明文会破坏它。刷新结果只留在桥进程内存中 | | **不记录对话内容** | 开启日志时只记录模型名、消息数、工具数 | | **不绕过鉴权** | 只驱动使用者**自己已登录**的账号;不提供、也不接受任何绕过认证的手段 | | **不外发数据** | 除发往 WorkBuddy 上游(`copilot.tencent.com`)的模型请求外,无任何遥测或回传 | --- ## 凭据是如何被处理的 ``` WorkBuddy.exe(以 ELECTRON_RUN_AS_NODE 运行) │ 返回 { atRestSecretKey, ... } ← 只读客户端自述,不落盘 ▼ SHA256 → 32 字节字段密钥(进程内缓存) │ ▼ 解开 envelope → 明文 JWT(仅存在于内存) │ ▼ Authorization: Bearer ──► copilot.tencent.com ``` 诊断功能(控制台页面、`tools/doctor.mjs`)会读取凭据,但**只用于判定**, 返回结构里只有: - 令牌**长度**(用于确认非空且形态正常) - 是否以 `eyJ` 开头(用于确认是 JWS 而非解密失败的产物) - 账号 uin、有效期、`keyId` 是否吻合 控制台的 API 响应中**不包含任何上游令牌片段**。`.credentials.yaml` 也只读取键名、不读值。 > **唯一的例外:本地回环令牌**(`WORKBUDDY_LOCAL_TOKEN`)。 > `GET /api/clients` 会原样返回它,因为控制台的「客户端接入」面板要让人把它填进 > 客户端 —— 不给值,这个面板就没有意义。 > > **默认值不再是固定串。** 首次运行时会生成一个 24 字节的随机令牌并写入 > `dsh-plugin/.bridge-token`(权限 0600,已 gitignore),之后一直复用它; > 控制台与 DSH 插件读同一个文件,保证两边一致。 > > 早先的默认值是硬编码的 `wb-local-bridge` —— 那是个**公开口令**,任何人 > (包括能绕开 Origin 检查的网页脚本)都能拿它调用桥、消耗账号配额, > 等于没有防护。除默认值外还有两处必须同时成立才算安全,见下。 > > 它**不是上游凭据**(上游凭据全程不出桥、不落盘、不进日志),作用仅是防止同机 > 其它程序误用这个回环端口。接口只绑 `127.0.0.1`。**改动这条边界时,请连带更新 > 本段。** ### 回环端口的实际防护(三条同时成立) | # | 机制 | 位置 | 说明 | |---|---|---|---| | 1 | **令牌始终必需** | `bridge/workbuddy-bridge.mjs` 的鉴权闸门 | 未配置时自动生成随机令牌并打印到启动日志;**不存在「无令牌即放行」这条路径** | | 2 | **比较是常数时间** | `safeEqual()`(`timingSafeEqual`) | 避免按字节短路比较泄漏令牌前缀 | | 3 | **写入需要预检** | `x-workbuddy-panel: 1` 头 | 强制跨站请求走 CORS 预检,浏览器不会自发带上它 | > ⚠️ 第 3 条只对浏览器生效。**本机其它程序**(脚本、其它应用)可以任意伪造头, > 唯一的拦阻是第 1 条的令牌。所以令牌绝不能是可猜的固定值 —— 这正是上面 > 把默认值改成随机的原因。 ### 控制台自己也是一个端点(知道这条,你才能正确评估风险) 控制台(`127.0.0.1:8792`)**没有身份认证**。其中 `GET /api/connect` / `GET /api/clients` 会返回**桥的令牌**(面板要显示与复制它),`/api/diagnose` 与 `/api/models?refresh=1` 会**真的干活**(跑诊断、强制打上游)。 自 2026-10-10 起,这几类接口和写操作一样要求带自定义头 `x-workbuddy-panel: 1` (控制台页面每个请求都自动带;跨站请求带不上自定义头,会先被 CORS 预检挡住): ```cmd curl -H "x-workbuddy-panel: 1" http://127.0.0.1:8792/api/connect :: 不加这个头 → 403 missing x-workbuddy-panel header ``` > **这挡的是"任意本机进程一句 curl 就拿走令牌"**,挡不住"能读你文件的进程"—— > 后者是同一台机器上的信任边界,见下面的风险声明。Windows 上 127.0.0.1 > **不按用户隔离**,所以共用机器上更要谨慎。 **多用户机器上的建议**:不要在共用机器上让控制台/桥常驻;用完就关 (`启动.cmd` 起的进程关掉窗口即可)。完整评估与未做的两步见 [客户端接入审计](CLIENT-CONNECT-AUDIT.md) 的 R2。 ### 接入备份里也有令牌 「一键接入」每次写入前会把客户端配置**整份备份**到 `.backup/client-configs/<客户端>/`(或 `%USERPROFILE%\.workbuddy-bridge\client-configs\`)。 从第二次写入起,备份里就带着上一次写进去的令牌;撤销记录(`applied.json`)的 `restore.section` 也可能带着更早的令牌。这些文件与客户端配置**同样敏感** —— 2026-10-10 起本项目会在写入后自动收紧该目录的权限(Windows 用 `icacls /T`, POSIX 用 0700/0600),并如实回报结果。 自查一行: ```cmd icacls "%USERPROFILE%\.workbuddy-bridge\client-configs" /T :: 出现 Authenticated Users / Users / Everyone → 没收紧,建议手工处理 ``` --- ## 你会看到的敏感信息 以下文件**包含有效凭据**,请勿提交、勿分享、勿放入备份同步目录: | 文件 | 内容 | |---|---| | `%LOCALAPPDATA%\CodeBuddyExtension\Data\Public\auth\*.info` | 加密后的 access/refresh token | | `~/.dsh/.credentials.yaml` | 各 provider 的 API key(含本项目写入的占位值) | | `~/.workbuddy/keyblob` | 客户端主密钥的包裹信息 | | `dsh-plugin/.bridge-token` | 本地回环令牌(随机生成;已 gitignore) | | `~/.codex/config.toml`、`~/.claude/settings.json`、`opencode.json` | 一键接入写进去的**回环令牌**(写入后自动收紧权限) | | `.backup/client-configs/**` | 上述配置的**整份备份**(含历史令牌;已自动收紧) | `.gitignore` 已排除 `*.info`、`.env`、`*.bak-*`、`.bridge-token` 等模式。 > 本项目写入 `.credentials.yaml` 的值是**本地回环令牌**(就是上面随机生成的那个, > 或你在 `.env` 里显式设的 `WORKBUDDY_LOCAL_TOKEN`),不是上游凭据——它只用于 > 满足 dsh 侧"必须提供 API key 引用"的要求。 --- ## 风险声明 1. **非官方路径。** 本项目通过客户端的公开原生接口与上游网关通信,属于互操作性实现。 上游随时可能修改协议或封禁该方式,**可用性无任何保证**。 2. **服务条款。** 使用前请自行确认符合你与 WorkBuddy 之间的服务条款。把账号额度 转供给其他程序使用,可能触及你所在环境的合规要求。团队或商用场景,正确做法是 申请官方 API 访问权限。 3. **额度归属。** 桥消耗的是你自己账号的配额。控制台的「对话测试」同样会消耗少量额度。 4. **无担保。** 按 MIT 许可,本软件"按现状"提供,不附带任何明示或暗示的担保。 --- ## 计费与用量核对 **桥不引入任何新的计费**:它只转发你自己账号的请求,消耗该账号的套餐额度; 桥的本地账本(`bridge/usage.jsonl`,只含元数据)与控制台「用量统计」里的积分合计 取自这些响应里的 usage/credit 字段,**不上报给任何第三方**。 但「经桥调用」与「在客户端里直接使用」**是否按同一口径计入**,取决于上游策略—— 这一点本机无法自行保证,建议主动核对: 1. 挑一个正常使用的时段(比如一整天),记录控制台「用量统计」的**积分合计**; 2. 与客户端内的用量页并排对比:**量级与趋势应一致**(口径可能不同——例如客户端把 桥请求归入某类调用——数值不必逐分相等); 3. **发现系统性偏差**(客户端用量远大于桥账本、或出现非预期的额外扣费):立即停止 经桥调用并排查。本项目无法也不应替你解释上游计费。 --- ## 建议的使用姿势 - 保持 `127.0.0.1` 绑定,不要为了"方便其它设备访问"而改成 `0.0.0.0` - 不要长期高频自动化调用——既无必要,也更容易触发上游风控 - 换机器或重装客户端后,重新登录一次即可;不需要手工搬运任何凭据文件 - 若不再使用,删掉 `~/.dsh/settings.yaml` 中本项目生成的分节即可,桥本体无残留