dsh-keychain-credentials:把 DSH 凭证放进 macOS 钥匙串

前言

DeepSeek Harness(DSH)通过 ctx.credentials 为适配器与工具提供 API Key、会话记录等敏感数据。默认的 dsh-credentials-local 会把内容写在 $DSH_HOME/.credentials.yaml,权限虽是 0600,但工具进程(bash、读文件类工具)与 DSH 同属当前用户,模型侧仍可能用 read、cat、grep 等方式读到明文。若你把 profile 目录纳入备份、同步或 git,凭证还会跟着文件一起外流。

下面介绍社区插件 dsh-keychain-credentials(维护者 nengong-ai):在 macOS 上用系统登录钥匙串承载 DSH 凭证,磁盘上不再保留可被直接 cat 的凭证文件。分类为 admin-security,当前 GitHub 星标为 0。

这是什么

dsh-keychain-credentials 是面向 DeepSeek Harness 的纯 JavaScript 凭证 Provider,实现 ctx.credentials 的完整 seam:refs(如 API Key 引用)与 records(如 client-connection/browser-session 等结构化记录)都写入 macOS 登录钥匙串,而不是明文 YAML。

与只实现 refs、仍让 session records 落回明文文件的 Provider 相比,该插件覆盖 seam 的两半;安装无需 Swift、代码签名或 Xcode。

核心功能

相对默认本地文件的改进

  • 密钥不再以文件形式存在,不会进入备份目录、同步盘或 git 仓库。
  • 读取门槛从「任意读文件原语」提高到「同用户进程需调用 /usr/bin/security」——有实质提升,但不是绝对隔离。

诚实说明:仍做不到什么

登录钥匙串在已解锁状态下(默认登录后即解锁),同用户进程可通过 /usr/bin/security 读取条目,且 CLI 受 ACL 信任、通常无二次提示;具备无限制 shell 且知道去查钥匙串的智能体仍可能外传。若要更硬边界,需 OS 级隔离(例如带私有 access group 的 broker,或独立 OS 用户),并可配合限制工具子进程的沙箱。

行为与 seam 契约

  • 进程环境变量优先于钥匙串(单次运行意图覆盖存储)。
  • 空值视为不存在;环境变量只读 shadow 时,set/unset 会拒绝。
  • describe 只检查是否存在,不读明文,避免状态查询把密钥拉进 agent 进程。
  • 调用 security 时错误信息做脱敏(退出码与 stderr,不含可能带密钥的命令行)。
  • 密钥经 stdin 传给 security,不进 argv,避免出现在 ps。
  • 超过 128 字节的值用 security -i 写入(stdin 密码提示会静默截断);写完后通过读回确认。

其它选型理由(README 自述)

  • 无 Touch ID / 密码弹窗:读写 deliberately 不打扰用户(与每次操作都弹窗的 keyringseam 类方案是不同取舍)。

环境要求

  • 操作系统:macOS(依赖 /usr/bin/security);package.json 中 engines.node 为 >=20,os 为 darwin。
  • DeepSeek Harness:≥ 0.1.0-rc.6(peer 范围覆盖 0.1.x 与 0.2.0-rc.1)。
  • DSH 0.2 及更新版本:插件必须以包形式挂载——安装进 profile 或链接到其 node_modules,并在配置里用包名引用;指向绝对路径 index.js 的行在 0.2+ 上不可用(peer 兼容性门禁与 asar 内 host 解析限制)。

安装与启用

官方安装命令如下(<profile> 换成你的 profile 名):

dsh plugin --profile <profile> add dsh-keychain-credentials
# or from source:
dsh plugin --profile <profile> add github:<you>/dsh-keychain-credentials

安装后,包内 cordis.patch.yml 会禁用默认 dsh-credentials-local 并挂载本 Provider。若需手写 patch,可在 ~/.dsh/profiles/<profile>/cordis.patch.yml 或 --patch <file> 中加入:

- id: credentials
  disabled: true
- insert:
    - id: credentials-keychain
      name: dsh-keychain-credentials     # 包名,不是绝对路径;插件须已装/链接进该 profile
      config:
        servicePrefix: dsh-credentials   # keychain service prefix
        account: dsh                     # keychain account name

插件版本以发布包为准(资料中 package.json 为 0.2.0);许可证 MIT。

典型用法

凭证引用名对应钥匙串条目的 account;service 前缀默认与配置中的 servicePrefix 一致(示例为 dsh-credentials)。用系统 CLI 写入一条 API Key:

security add-generic-password -U -s dsh-credentials -a DEEPSEEK_API_KEY -w 'sk-…'

LLM 适配器会按引用名在请求时解析,轮换密钥后无需重启 DSH。

开发者在仓库内可安装依赖并跑测试(会操作真实登录钥匙串下的测试前缀 dsh-credentials-test,不写真实密钥):

npm install   # or pnpm install — devDependencies supply the seam packages
npm test

适用场景与注意

适合:在 macOS 上长期跑 DSH、希望 refs 与 records 都离开明文 YAML、又不想引入 Swift 构建链的开发者。

不适合:非 macOS 环境;或要求「模型与工具完全无法触达密钥」的 threat model——本插件只抬高攻击门槛,不能替代 OS 级隔离。

安装前:插件与 DSH 同用户、同进程权限运行;启用前请自行审阅 GitHub 源码 与许可证。社区插件目录 skillhub.cn 为独立站点,与 DeepSeek / 幻方无官方从属关系,并非官方应用商店。

小结

dsh-keychain-credentials 用 macOS 登录钥匙串替代 $DSH_HOME/.credentials.yaml,同时支持 refs 与 records,纯 JavaScript 安装即用。它不能消除同用户下通过 security 读取的可能,但可避免凭证以普通文件形式被模型常用读路径扫到。

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜