dsh-tui-secret:在 dsh-TUI 里安全录入与管理凭证

前言

在 DeepSeek Harness(DSH)里用智能体写脚本、调 API 时,密钥和密码往往要进环境变量或配置文件。若把明文写进对话、日志或让模型直接拿到字符串,一旦上下文被导出或工具链记录输出,泄露面会很大。常见做法是本地凭据文件加权限、或完全手工粘贴——前者仍缺「Agent 要用时你怎么授权」的统一入口,后者又打断流程。

下面介绍社区插件 dsh-tui-secret(维护者 zerodegress):面向 dsh-TUI,通过 /secrets 全屏场景做掩码录入,并把值只写入 DSH 自带的 ctx.credentials 接缝;插件不回显、不记录、不把秘密放进对话。Agent 侧仅能通过两个运行时工具发起「请求录入」或「在子进程里使用」,返回值里只有状态或已脱敏的输出。

这是什么

dsh-tui-secret 是 dsh-TUI 插件,分类为 admin-security。一句话定位:为 dsh-TUI 提供安全的秘密录入(/secrets:掩码输入 → 引用列表 → 删除确认),并约束 Agent 只能通过 DSH 凭据存储与受控子进程接触秘密,而不是把值交给模型或会话。

当前 package 版本为 0.2.0,许可证 MIT,要求 Node.js ^22.19 || >=24。官方写明支持的目标宿主为 @deepseek-harness-tui/dsh-tui 0.16.x,其他 TUI 实现不在范围内。

核心功能

用户侧:/secrets 场景

重启 TUI 后输入 /secrets 进入全屏场景:

  • 按 a 新建引用:先填名称,再输入值;输入时按字符显示 •(可通过配置改为完全不显示长度)。
  • 列表只展示配置状态、来源与可写性,不展示秘密值;d 删除选中引用(需 y 确认),v 撤销该引用上的 Agent 权限,R 撤销全部 Agent 权限(y 确认,已存储的值保留)。
  • 引用名须符合 DSH 规则:以大写字母开头,仅 A-Z、0-9、_,最长 64 字符;DEEPSEEK_ / DSH_ 前缀由宿主保留,插件会当场拒绝并给出可读原因。

配置项(写入 profile 的 cordis.patch.yml 片段)示例:

- insert:
    - id: dsh-tui-secret
      name: dsh-tui-secret
      config:
        entryCommand: secrets   # 可改成其他命令名
        echo: dots              # 每字符一个 •;设为 none 则连长度也不显示

echo: none 适用于共享屏幕或录屏时连长度都不想暴露的场景;默认 dots 会在屏上显示与秘密等长的点阵。

Agent 侧:两个工具

宿主没有工具清单契约,插件在运行时注册:

工具 参数 返回
request_credential ref, purpose stored / cancelled / refused
use_credential ref, argv[], timeoutMs? exitCode, stdout, stderr, redacted, timedOut, aborted, injectedAs

request_credential 会在你面前弹出卡片:显示名称、用途,以及四种授权(不允许 / 一次 / 本会话 / 直到某时间);值由你在卡片上键入,模型不能通过工具参数传入秘密。同意后值进入 ctx.credentials,工具结果只有状态,秘密不进对话。

use_credential 在单独子进程里执行一条命令:秘密以 injectedAs 报告的环境变量名注入该子进程,不会进入你或 Agent 所在的 shell;返回的 stdout/stderr 中凡出现该值的位置会替换为 [credential]。argv 以数组交给插件并逐元素引用,模型不能直接向 shell 塞原始文本;需要管道或变量时需自行写成例如 ["sh","-c","…"] 的形式。

插件不注册 shell 环境贡献者,因此 $NAME 不会进入模型执行所在环境;面向模型的表面只有上述两个工具。

安装与启用

支持的 TUI 版本见上文。在 shell 中:

dsh plugin --profile dsh-tui add github:zerodegress/dsh-tui-secret

或在 TUI 内:

/plugin install https://github.com/zerodegress/dsh-tui-secret

也可在 profile 的 cordis.patch.yml 中增加与包内 cordis.patch.yml 相同的一行插入配置(安装 bundle 机制会应用)。完成后重启 TUI,执行 /secrets(或你配置的 entryCommand)。

典型用法

  1. 手工维护密钥库:/secrets → a → 输入引用名与掩码下的值 → Enter 写入 DSH 凭据存储。
  2. Agent 索要凭证:模型调用 request_credential(ref, purpose) → 你在卡片中选择授权范围并输入值 → 对话里只见 stored 等状态。
  3. Agent 需要用密钥跑一条命令:在已存储且授权的前提下,模型调用 use_credential(ref, ["your","cli","args"]) → 你在本地凭据中已有该 ref;子进程拿到环境变量,对话与工具返回只见脱敏输出与退出码。

键位摘要:↑/↓ 移动选择,Enter 下一步或确认写入,Esc 回退;在 Agent 请求的卡片上,权限仅用方向键选择,数字键属于秘密内容本身。

存储与实现要点

内容 位置 说明
秘密值(DSH 托管) <DSH_HOME>/.credentials.yaml 模式 0600,由 provider 保证
引用名索引(本插件) $DSH_TUI_HOME/dsh-tui-secret/refs.json(默认 ~/.dsh-tui/…) 仅名称索引,非秘密库;文件 0600,目录 0700,原子写入

因 ctx.credentials 无 list(),插件用 refs.json 记录曾录入的引用名;损坏时按空列表读取,不会盲目覆盖。值只经 ctx.credentials.set(ref, value) 写入,插件不写 .credentials.yaml 本体,React 状态里也不保留秘密(使用 useRef 并在写入前丢弃本地副本)。

开发侧:npm test 会校验 dsh-plugin.json 与 TUI profile,并对场景做逐帧测试,清单漂移可在本地失败。

适用场景与注意

适合在 dsh-TUI 0.16.x 下长期本地开发、又需要让 Agent 偶尔使用 API Key、数据库密码等、且希望默认不把秘密串进 LLM 上下文的开发者。与「把密钥写在 .env 并让模型读文件」相比,本插件把录入、授权与使用拆成 UI 与两个受限工具,并强调输出脱敏。

安装前请注意:

  • 插件以当前 dsh 进程权限运行;安装前应自行查看 GitHub 源码 与 MIT 许可证,社区目录 SkillHub 插件页 与 DeepSeek / 幻方无官方从属关系,并非官方应用商店。
  • 已知限制:DSH 凭据存储为明文 YAML(0600 仅防其他本地用户,沙箱限制写不限制读);无加密。若威胁模型包含本机其他进程或备份泄露,需额外加密或外部秘密管理,不能单靠本插件。
  • 缺少 ctx.tuiScenes 接缝时场景会静默无响应,但不会拖垮 TUI 启动。

结尾

dsh-tui-secret 把「秘密录入、列表与撤销」收进 /secrets,并把 Agent 可触达面收窄为 request_credential 与 use_credential,值只走 DSH 凭据接缝与子进程环境。若要查阅元数据或安装入口,可见 SkillHub:zerodegress/dsh-tui-secret 与仓库 github.com/zerodegress/dsh-tui-secret。

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

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

Xiaoye