前言¶
在 DeepSeek Harness(DSH)里跑智能体时,工具会把命令输出、文件内容写进模型上下文和本地会话日志。DSH 自带的 ui-secret-mask 只在浏览器渲染层把形如 sk-... 的字符串画成 ***,底层数据仍以明文进入后续请求前缀、写入 ~/.dsh/sessions/**/session.v4.jsonl.zstd(zstd 压缩,不是加密),也可能作为工具参数拼进出站 URL 或 curl。提示注入若把密钥塞进参数,仅靠 UI 遮罩挡不住。
下面介绍社区插件 dsh-veil(维护者 yhl4466),在官方扩展点 tools/pre-execute / tools/post-execute 做确定性强制处理:不改 DSH 源码、不注册新工具,文档称 零 schema 税。分类为 admin-security。
这是什么¶
dsh-veil(包名 dsh-veil,README 副标题「密钥面纱」)是 DSH 的执行层凭据护栏:在密钥进入模型上下文、会话日志或出站请求之前拦截或抹除;阻止读取凭据库;对 web/MCP 等来源的结果标记不可信边界。许可证 MIT,当前 package 版本 1.0.0(以仓库 package.json 为准)。
与 UI 遮罩的差别¶
| 方面 | ui-secret-mask |
dsh-veil |
|---|---|---|
| 作用层 | 浏览器显示 | 工具执行前后钩子 |
| 模型可见副本 | 仍可能含明文 | 结果脱敏后再进入上下文 |
| 会话日志 | 不保证改写 | 实测 tool/result 事件存脱敏后副本 |
| 读凭据文件 / 外带密钥 | 不拦截 | 可配置拒绝 |
四层能力¶
README 用一张表概括四条规则,对应 cordis.patch.yml 里的开关:
| 层 | 钩子 | 行为 |
|---|---|---|
| A 结果脱敏 | tools/post-execute |
进入上下文/日志前,抹掉 ~/.dsh/.credentials.yaml 与环境变量中的 KEY/TOKEN/SECRET 等已知真值,以及常见形态(sk-、ghp_、AKIA、JWT、Bearer、PEM 私钥、KEY=value、带密码连接串等) |
| B 凭据读拦截 | tools/pre-execute |
参数指向 .credentials.yaml、.ssh/*、.aws/credentials、.npmrc、.netrc、.git-credentials 等时拒绝(含 shell 拼接) |
| C 外发拦截 | tools/pre-execute |
web/mcp、带 URL、curl/Invoke-WebRequest/ssh 等出站类调用参数中出现密钥则拒绝 |
| D 信任边界 | tools/post-execute |
为 web/mcp 结果包一层确定性「不可信数据」边界,降低间接注入成功率 |
安装与启用¶
从 GitHub 安装(README 原文命令):
# 从 GitHub 安装
dsh plugin add github:yhl4466/dsh-veil
# 或本地目录(开发时)
dsh plugin add <本目录>
维护者在 desktop profile 验证过:Loader entry 为 include:dsh-veil,fiberPhase=active。社区目录页:skillhub.cn/plugins/yhl4466/dsh-veil;源码:github.com/yhl4466/dsh-veil。
配置¶
在 profile 的 cordis.patch.yml 中覆盖插件配置。注意:config 块是整体替换,覆盖时需把需要保留的字段一并写全。
- id: dsh-veil
name: dsh-veil
config:
redactResults: true # A 结果脱敏
denyCredentialReads: true # B 凭据读拦截
blockSecretEgress: true # C 外发拦截
envelopeUntrusted: true # D 信任边界
watchCredentialStore: true # 从 ~/.dsh/.credentials.yaml 读真值(只读,不落盘)
exemptTools: [] # 不脱敏的工具名
untrustedTools: [] # 额外声明为不可信来源的工具名
extraSecrets: [] # 额外已知密钥(字符串数组)
protectPaths: [] # 覆盖受保护路径列表(整体替换)
典型用法:查看状态¶
输入 /veil(不进工具列表,不占每次请求的 token)。示例输出形态如下:
dsh-veil 凭据护栏
开关:结果脱敏=开 凭据读拦截=开 外发拦截=开 信任边界=开
本会话:脱敏 2 次 / 拦读 1 次 / 拦外发 0 次 / 加边界 3 次
近 24h 全局:...
命中规则 Top5:...
账本路径:~/.dsh/veil/ledger.jsonl。只记录「命中哪条规则、几次」,不写密钥原文;超过 2 MB 自动轮转。
设计约束¶
与 dsh-fence 共用一套缓存契约,README 强调四点:
- 前向一次性:结果仅在进入会话那一刻改写一次,不回改已发送消息。
- 确定性:同一
(工具, 参数, 结果)每次得到相同字节(信任边界不含时间戳)。 - 失败开放:脱敏异常时放行原结果,不把成功调用变成报错。
- 不落明文:账本与插件相关日志不含密钥值。
已验证行为与已知边界¶
仓库提供 test/veil-test.mjs,README 记载 npm test 下 16/16 通过,覆盖:sk- 与凭据库真值脱敏、凭据读被拒、curl 带密钥被拒;普通读文件、grep pattern、含 URL+密钥的 write 正文、文档里提到 .credentials.yaml 的 shell 写法等不误拦;信任边界确定性、账本无明文、图片块透传、/veil 输出无明文等。
使用前需知边界(摘自 README):
- 模型自己生成的内容(assistant 文本、tool-call 参数、手动粘贴的消息)不经过
tools/post-execute,不在本插件范围;输入侧可配合dsh-secret-paste一类插件。 - 若链上 spill /
dsh-fence先把超大结果落盘,落盘副本可能仍含原文;凭据读拦截已关掉主要读入口。 - 图片/二进制不做脱敏。
- UI 工具卡片仍显示原始结果(脱敏只作用于模型可见副本),便于本地排查。
适用场景与注意¶
适合在 DSH 中长时间开工具、读仓库与环境、并调用 web/MCP 的开发者,希望把密钥挡在执行层而不是只看 UI。插件以当前 dsh 进程权限运行,安装前请自行审阅 源码与 MIT 许可证,确认与自身合规要求一致。
DSH 生态强调「一切皆插件」;SkillHub 为社区目录,与 DeepSeek / 幻方无官方从属关系。
结尾¶
dsh-veil 把「看见密钥被星号挡住」推进到「上下文和出站路径上少一份明文」。四层开关可按 profile 裁剪;用 /veil 看本会话与近 24h 命中情况即可做日常核对。
- 目录页:https://www.skillhub.cn/plugins/yhl4466/dsh-veil
- GitHub:https://github.com/yhl4466/dsh-veil