ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

DSHCode 凭据安全设计:CredentialRef 引用机制如何让 API Key 远离明文配置

DSHCode 凭据安全设计:CredentialRef 引用机制如何让 API Key 远离明文配置

【免费下载链接】dshcode

Community desktop companion for DeepSeek Harness — one-click Electron app for macOS and Windows

项目地址:https://gitcode.com/gh_mirrors/ds/dshcode
点击查看免费下载

DSHCode 是 DeepSeek Harness 的社区桌面伴侣应用。它的凭据安全设计核心是CredentialRef 引用机制:配置文件只保存 API Key 的「名字」,明文密钥被隔离在独立的凭据存储中,从架构上让 API Key 远离明文配置、远离同步与渲染。

一句话概括:设置里写的是DEEPSEEK_API_KEY,而不是sk-...。值与引用彻底分离,才是安全的地基。

为什么 API Key 不该写进配置文件

把 API Key 直接写进settings.yaml、cordis.yml或任何会被同步、共享、渲染进界面的文件,会带来一连串隐患:

  • 📤同步即泄露:配置进版本库或云同步,密钥跟着一起走。
  • 🖥️界面即暴露:设置界面若直接回显密钥值,等于把它交给每一个打开页面的人。
  • 🔄轮换即改配置:换一把密钥要改一堆配置文件,还要重启才生效。

DSHCode 的解法很干脆:配置只携带引用(reference),值由凭据提供者(provider)托管。这样配置文档天然「可安全同步、可安全渲染」,而密钥本身始终待在它该待的地方。

CredentialRef:把「值」换成「名字」

CredentialRef是一个品牌化(branded)类型,本质是一个符合 POSIX 规则的环境变量名,例如DEEPSEEK_API_KEY。它的作用只有一个——指代一份机密,而绝不是承载机密。

// 名字通过严格校验后,被打上品牌,从此与其他字符串不可混淆 const ref = credentialRef('DEEPSEEK_API_KEY')

命名遵循/^[A-Za-z_][A-Za-z0-9_]*$/——即标准 shell 标识符。这个「环境变量的形状」是刻意的:引用在解析时要穿越环境变量这一层,名字必须能同时当环境变量用。

围绕引用,凭据 seam(ctx.credentials)提供四个核心操作:

操作作用是否返回值
resolve(ref)解析出当前密钥值与来源层✅ 仅内部调用
describe(ref)描述「是否已配置 / 来自哪 / 能否写」❌ 永不返回明文
set(ref, value)持久化保存一份密钥—
unset(ref)移除一份密钥—

关键在describe:它回答配置界面关心的问题,却从不暴露值。

📌 这套「只描述、不给值」的视图没有为值预留任何插槽,正是它让整个读取面可以安全地跨越 Remote 通信线。

相关定义见 packages/credentials/credentials/src/types.ts 与 seam 抽象 packages/credentials/credentials/src/index.ts。

四层来源:密钥到底从哪来

当 DSHCode 需要某份密钥时,会按一个固定顺序查找,第一个有值者胜出:

来源可写?优先级
启动时的进程环境变量(如DEEPSEEK_API_KEY=… dsh)🔒 只读⭐ 最高
凭据文件$DSH_HOME/.credentials.yaml✍️ 可写高
项目目录.env(<启动目录>/.env)🔒 只读中
主目录.env($DSH_HOME/.env)🔒 只读最低

这个顺序体现了一条诚实的优先级:

  • 启动环境永远赢——它代表「这次运行的明确意图」(比如 CI 的密钥、容器的-e),无法从产品内部编辑,所以被显式标记为只读,写入会被拒绝,而不是被静默影子覆盖。
  • 凭据文件压过所有.env——你在设置页保存的密钥立即生效,即使某个.env里还躺着一把更旧的密钥,也绝不会把它挤掉。
  • .env只在没存值时兜底。

本地存储实现见 packages/credentials/credentials-local/src/index.ts,它管理的正是$DSH_HOME/.credentials.yaml这个私有文件。

配置界面只写不回传

在 DSHCode 的设置 → 模型页面填入 API 密钥,是理解这套机制最直观的入口:

这个 API 密钥字段是**只写(write-only)**的:

  • 你保存后,页面只会收到一份脱敏描述符(configured/source/writable),永远不会收到明文密钥。
  • 密钥被写进$DSH_HOME/.credentials.yaml,而设置里只留下一行凭据引用。

添加自定义提供方时同样如此——表单里的「API 密钥」只进不出:

表单中的Provider ID是持久的,因为请求、已保存会话、模型默认值和凭据引用都会用它来派生引用名。

⚡ 单向流动是铁律:值可以「写进去」,但没有任何读取路径会把它「带出来」。

这条原则在 Remote 侧由CredentialsController强制——它的describe/set/unset中,没有任何方法会返回密钥值。

旋转即时生效:每次请求都重新解析

凭据 seam 有一条贯穿性的规矩:消费方在每次操作时重新解析,绝不跨操作缓存。

对 LLM 适配器而言,「一次操作」就是「一次模型请求」。DeepSeek 适配器在每次请求时都会现查密钥:

const hit = await credentials.resolve(ref) // 每次请求都重新解析

这意味着:

  • 🔁换密钥 = 下一次请求就用新密钥——无需重启、无需改任何配置文件。
  • 🧯空值即「无」:存一个空字符串会被直接拒绝,空值永远不会伪装成「已配置的机密」。

这段逐请求解析逻辑见 packages/llm/llm-deepseek/src/index.ts。完整子系统的词汇与契约,可查 docs/subsystems/credentials.md。

凭据文件的权限隔离

值落在$DSH_HOME/.credentials.yaml,这是一份带版本的 YAML 文档,只包含两节:refs(按环境变量名存放密钥值)与records(按插件存放持久化凭据)。

围绕这份文件,DSHCode 做了多层防护:

  • 🔐仅属主可读:产品以属主权限创建它;在 POSIX 上,拒绝加载任何「其他用户可读」的文件,并提示你执行chmod 600。
  • 🤖从不把路径交给 Agent:产品的工具进程虽然以你的 OS 身份运行,但产品绝不告诉它文件路径,也从不把文件内容加载进环境——要拿到值,需要一次「明知路径却故意去读」的动作。
  • 🤐诊断绝不引用密钥:解析报错只携带错误码与位置;键名可打印,值不可——因为 YAML 解析器自己的报错会引用「出错的源行」,而在这份文档里那行正是密钥本身。

官方文档把这层隔离称作「谨慎(discretion)而非边界」:文件权限挡不住同属主的 Agent,因此「必须把密钥与自家 Agent 彻底隔离」的部署,应选用其他存储提供者,而非依赖权限位。

快速上手:在 settings.yaml 中引用密钥

手动配置时,你同样只需写「引用名」,而非密钥本身。一个自定义网关的路由长这样:

llm-pi-ai: providers: my-gateway: apiKeyEnv: GATEWAY_API_KEY # 这是引用名,不是密钥值 api: openai-completions baseURL: https://gateway.example/v1 models: - id: my-model

apiKeyEnv的值(GATEWAY_API_KEY)只是一个凭据引用。真实的GATEWAY_API_KEY值要么存在凭据文件里,要么由启动环境提供——配置文件里自始至终看不到任何sk-...。用户指南见 docs/user/guide/providers.zh.md。

常见错误排查

  • MISSING_CREDENTIAL:通过模型页存储该提供方的密钥,或提供被引用的环境变量。
  • 某密钥在界面里显示「只读」、写不进去:它来自启动环境(DEEPSEEK_API_KEY=… dsh)。请先在启动 shell 里清掉该变量,再保存新值。
  • 想「清空」密钥:存空值会被拒绝——请用unset移除,而不是存一个空字符串。

小结

DSHCode 的凭据安全不靠某一处加密,而靠一套分层的职责隔离:

  1. 引用与值分离——CredentialRef让配置只说「名字」,不说「值」。
  2. 读取永不回传——describe与 Remote 层都没有值能走的通道。
  3. 每次操作重解析——密钥轮换即时生效,空值即无。
  4. 文件权限 + 路径隔离 + 静默诊断——把值锁在属主可读的私有文件里,且不交给 Agent。

这套设计让「API Key 远离明文配置」不是一句口号,而是从类型、seam、存储到界面贯穿始终的默认行为。

【免费下载链接】dshcode

Community desktop companion for DeepSeek Harness — one-click Electron app for macOS and Windows

项目地址:https://gitcode.com/gh_mirrors/ds/dshcode
点击查看免费下载
上一篇:vLLM快速部署教程:3步在DGX Spark上跑通NVIDIA-Nemotron-3.5-Super-VL-120B-A12B-NVFP4-LiLiCorr投机解码
下一篇:本地双语语义搜索新选择:Octen-Embedding-4B-MLX-4bit 中英文检索实战指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进