credential-vault.md 12 KB

Bot 内置密码库(首期)

部署目标是 Hermes 执行节点,用户通过专用界面手动输入主密码。默认锁定,重启不自动解锁。密码库不是 Hermes 的环境变量或工具配置。

密码学与存储

固定依赖 libsodium-wrappers-sumo 0.8.4(官方 npm registry,禁用安装脚本),使用其 Argon2id13 和 XChaCha20-Poly1305。每个账号独立随机 256-bit DEK;主密码经随机 128-bit salt、3 次迭代、64 MiB 内存派生 KEK,包装 DEK。每次包装、写入都使用独立随机 192-bit nonce。AAD 绑定格式版本、账号、vault ID,以及 KDF 参数或文档修订;元数据与秘密一起加密,没有同目录静态解密密钥。

格式 v1 的文件原子替换并 fsync;写入中断应留下旧或新的完整可解密版本。主密码轮换同时更换 salt 和 DEK。加密备份保留 owner 身份,只恢复到未初始化且账号身份相同的库;不能覆盖现有库。迁移必须保留账号 ID。备份可用其导出时的主密码解密,改主密码不会使旧备份失效;遗失主密码无法恢复。没有离线文件回滚检测或硬件密钥保护。

解锁 DEK 只存在 broker 内存,固定到期、锁定、关闭时清除可控字节缓冲。JS 字符串、GC、WASM、交换区和进程转储不提供安全擦除保证,必须配合操作系统隔离;不能据此称“密码永不进入内存”。UI/API 不提供读取密码或私钥明文的接口;编辑秘密是单向替换。

执行边界

同 OS 用户的 Hermes 任意 shell 可以读取同用户文件或访问进程/IPC,因此单纯子进程、0600 权限、secretref 或加密 DB 不构成隔离。真实部署前需人工批准独立 OS 身份/可信沙箱、私有 IPC、控制面访问权限以及浏览器进程/资料目录边界。Web 管理面也不能与拥有任意本机 shell 的 Hermes 共用可信身份。

首期正式浏览器与 SSH executor 未启用。即使库已解锁也不能退回通用 fill、host_shell、环境变量或临时密钥文件;没有“模拟登录成功”的生产实现。网站登录最终需要独占阶段、精确 HTTPS origin/frame/form 目标校验,冻结模型 DOM/截图/请求/Cookie 访问;MFA/验证码由用户处理。SSH 需固定 host key,密钥认证优先,禁 agent forwarding 与任意 ProxyCommand;文件传输采用 SFTP,明文 FTP 不支持。

开发仅使用临时目录中的 dummy 凭据和本机测试夹具。真实秘密录入、真实登录、OS 用户/权限/守护进程安装及生产切换都不属于本轮本地实现操作。

官方说明:libsodium.js、Argon2id、XChaCha20-Poly1305。

首期可操作范围与接入

Web 的「Bot 模式 → 设置 → 密码管理」提供创建、手动解锁 5 分钟、加密条目 CRUD、立即锁定、60 秒单任务引用授权/撤销、加密备份/同账号恢复及主密码和 DEK 轮换。解锁前不展示条目元数据,编辑不读取原秘密。关闭/隐藏管理页会清除输入、取消待返回请求并尝试锁定;网络不可达时不能保证这条锁定请求送达,因此 broker 自身仍实行固定到期。不能保证清理浏览器/OS 的内存历史,录入只应在可信用户管理页面进行。

私有协议为 credential-vault/v1(HTTP JSON,经 Unix socket,禁止 Origin),没有 read-secret 命令;execute 仅接受单次短授权与固定范围,正式 CLI 未注入执行器时明确拒绝。每次 Web 控制进程重新握手都会锁定全部库并撤销旧授权。BFF 重启不会恢复授权或重放操作。UI/API GET /api/app/vault 返回状态、元数据、活动任务和待授权请求;其下 POST initialize/unlock/lock/rotate/backup/restore,POST entries/leases,PUT/DELETE entries/:id,DELETE leases/:id 均沿用当前登录、精确 Origin、CSRF 和 owner 校验;管理入口仅接受 HTTPS 或本机回环 HTTP。不依赖全局「允许不安全局域网」选项。

Runner 只声明 credential-ref-v1,没有 credential-executor-v1。授权绑定 owner、本次登录、Bot、活动 work ID、Runner ID/instance/epoch、精确 origin 或 SSH 主机/端口/host key、操作、凭据版本和到期时间。停止/取消/删除/权限变更/重连/锁定/轮换/条目改动使旧授权失效,迟到的解锁或 grant 响应不能恢复权限。旧 Runner 明确拒绝;离线/锁定时 Bot 在任务的 waiting 状态等待,最长 120 秒后返回未执行的等待结果。任务取消会释放等待并撤销授权。

Bot 工具只有 credential_refs 与 credential_request,输入严格为引用及操作,模型看不到用户名/密码/私钥/主密码/控制 token。refs 返回当前任务的允许目标;收到合法短授权后,生产 CLI 返回 manual_takeover_required / vault_executor_not_enabled。CLI 没有启用执行器的配置开关。测试构造器注入 FixtureWebsiteLoginExecutor 时声明 dummy-fixture,它只接受预先指定的 https://127.0.0.1:端口,验证临时测试 CA,向固定 /login 提交库中 dummy 账号密码,取得 Cookie 后访问 /protected 证明认证。禁止重定向、公共主机、全局代理和任意路径/表单;秘密和 Cookie 都不会返回模型。此适配器从真实 WorkspaceRuntime 工具目录/调用上下文、用户授权 API、私有 IPC 完成认证,重复工具 call ID 只收到原脱敏回执,不再登录。这是工作的本地 dummy 登录适配器,尚非通用网站浏览器适配器;SSH/SFTP 目前只有存储、目标和授权校验,没有执行实现。不能将它作为 OS 隔离证据。

部署前需人工完成的边界(本轮未执行)

  1. 选择 Hermes 所在的同一执行节点,确认 Hermes 非 root 身份,并为 Web 管理面与 vault 分配不同于 Hermes 的非 root 可信服务身份。首期为同主机 Unix IPC;远程 Web → vault 网络通道尚未实现,不能将 Unix socket 暴露为 TCP 或经通用 Runner 转发主密码。
  2. 人工审核 broker、Web 管理面、配置、socket 父目录、控制 token、库目录的 ownership、ACL、进程调试/core dump、备份访问及管理浏览器隔离。代码检查私有权限和配置声明的 Hermes UID,但声明数字本身不是隔离证据;Hermes 的 shell 不得读取控制 token、管理面登录会话或访问私有 IPC。两者为同用户时直接拒绝,不自动改 OS 设置。
  3. 在该可信控制身份下人工准备 0700 私有目录,以及 0600 配置和高熵控制 token 文件;token 仅用于 IPC 认证,绝不是静态解密密钥。配置结构 { "home": "/私有库目录", "socket": "/私有连接目录/vault.sock", "tokenFile": "/私有连接目录/control.token", "hermesUid": 12345 } 中的 UID 是文档示例,必须填实测 UID,且不能与控制服务身份相同。不要把这些文件放入仓库或 Hermes 工作目录。
  4. 经后续部署批准后,使用 Node >=24、生产依赖和构建输出,人工前台执行 node dist-server/server/credentialVault/index.js --config /私有路径/vault.json。单实例控制避免两个 broker 同时写库;启动会检查而不会创建 OS 身份/安装守护进程。Web 配置 HERMES_YAOYAO_VAULT_SOCKET、HERMES_YAOYAO_VAULT_TOKEN_FILE、HERMES_YAOYAO_VAULT_HERMES_UID,它们只有路径/UID。未配置时 UI 明确离线;锁定或离线不自动降级。
  5. 用户亲自在专用 UI 创建并解锁。上线前还需验证真实 OS/IPC 攻击边界、HTTPS 管理通道及备份恢复,不把本地同进程 dummy 测试作为隔离验收。本轮没有实际创建服务身份、控制凭据、生产密码库或录入真实秘密。

未来受保护执行器需要独立安全实施与验收:限定操作及单次提交,执行前/后检查授权,撤销中止;结果只返回脱敏状态,执行断线或取消结果不明确时禁止自动重试。浏览器填充阶段必须独占并隔离 DOM、请求、Cookie、截图、CDP 与同 UID shell;登录后的站点操作也须走受限动作/脱敏返回,不能向模型开放可读 Cookie 的通用浏览器。SSH/SFTP 要独立短连接及已确认的 host key,不能允许 shell 自选命令、任意跳板/代理、端口转发、agent forwarding、密钥导出或明文 FTP。

本地验证

tests/server/credentialVaultStore.test.ts:密文与默认锁定、AAD 篡改、fresh nonce/修订、备份和轮换写入中断。credentialVaultBroker.test.ts:作用域、默认拒绝、单次消费、锁定/登出/撤权/取消/重连/修改/删除/到期的在途中止、脱敏审计及 symlink 拒绝。credentialVaultCoordinator.test.ts:dummy Unix IPC、迟到解锁/grant、会话与任务/Runner 失效、等待取消、HTTPS/旧 Runner拒绝。credentialVaultRoutes.test.ts 使用真实 Web/LocalAuth 但上游为 stub,检查认证/Origin/CSRF/登出联动。tests/client/credentialVaultPanel.test.ts:专用输入、无 localStorage、无明文回显、编辑空值保留、关闭/隐藏时取消并锁定。Runner 现有本机夹具验证能力声明。

这些测试不连接真实网站或 SSH;没有真实账号、跨 OS 身份穿透测试、移动端专用原生密码库 UI、真实适配器、端到端生产部署或真机验收。现有移动端与独立原生管理器不在首期范围。

首期验收记录(2026-09-30)

存储底座提交 9092831;UI、私有 broker/IPC、任务短授权、Runner 引用能力和工作的本地 dummy 网站登录工具链提交 771c72c。中间 d1650ef 是并行的客户端上下文统计工作,不属于密码库修改。版本保持 v0.4.77,私有密码库协议 v1,没有自行升版。

最终非 live 回归 vitest run --exclude 'tests/live/**' --maxWorkers=2 为 2144 passed / 7 skipped / 0 failed,其中密码库 6 个测试文件共 41 项通过,包括真实 WorkspaceRuntime 的 Bot 工具目录/调用、用户任务授权、私有 IPC、HTTPS dummy 实际认证、受保护页面访问及脱敏回执/调用去重。另有真实 Runner 夹具 29 项、LocalAuth 7 项通过。类型检查、Web/服务端 build、Runner build 均通过。首次默认并行全量为 2130 passed / 2 failed / 7 skipped:Kanban 无效 board 返回状态和十活动任务调度;两项隔离复验通过,降低 worker 并行度后的最终全量也通过,未放宽断言/超时。首跑失败根因尚未完全确定,不能宣称已修复产品缺陷。

日志/JSON 在本机 /tmp/yaoyao-vault-final-vitest.log、/tmp/yaoyao-vault-final-vitest.json、/tmp/yaoyao-vault-final-typecheck.log、/tmp/yaoyao-vault-final-build.log、/tmp/yaoyao-vault-final-runner-build.log;首次全量证据为 /tmp/yaoyao-vault-full-vitest.json,隔离复验为 /tmp/yaoyao-vault-isolated-failures.log。构建输出为 dist/、dist-server/server/credentialVault/ 和 .runner-build/runner.mjs,只进行了构建检查,没有打新签名安装包、推送、部署、重启生产或安装到日常设备;工作区并行附件修改另行负责,未混入密码库提交。

未验证的真实边界:不同 OS 身份间的隔离与攻击验证、部署后的 HTTPS 用户管理通道、通用网站浏览器登录/登录后权限控制、SSH/SFTP 实际连接、移动原生 UI、真实 Hermes/模型自主调用和生产数据恢复。上游 Hermes 模型/网关为测试夹具;Web/WorkspaceRuntime、工具 HTTP 路由、vault IPC、用户授权与本地 HTTPS 认证是实际代码执行。整个开发只接触 dummy 数据,未扫描 Keychain/.env/既有秘密库或录入真实秘密。必须先取得实际 OS/IPC 部署批准并验收,再另行实现和批准真实受保护执行器;当前不能安全启用真实网站/SSH 登录。