DeepSeek Harness Hub
← 返回列表

Ox0400/dsh-vault

DeepSeek Harnessspec-screened在 GitHub 查看 ↗
✓ 可直接安装

dsh-vault — 用于 DeepSeek Harness 的加密凭据保险库

自动检查通过:npm 包已发布且 engines 声明满足基线(声明 Node >=20);该结论来自程序自动检查,未经人工实机验证。 · 最近上游提交 2026/9/17 · 已提供中文文档

DeepSeek Harness 的加密凭据保险库 — AES-256-GCM + TOTP,模型工具 + 设置界面

综合分
37.2
GitHub 分
37.2
用户评分
★ Stars
11
周下载量
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add dsh-vault
npm 包 dsh-vault 已校验归属本仓库,走 npm 安装最省事
数据截至 2026/9/17(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
安装兼容性检查✓ 自动检查通过

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

npm 包dsh-vault @ 1.10.73
Node 引擎要求 >=20 · 基线 Node 22.19 满足
dsh CLI 依赖未声明 dsh 版本约束
入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后验证 2026/9/18 02:17:56

依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh-atomic-write@deepseek-ai/dsh-home-paths@deepseek-ai/dsh-llm@deepseek-ai/dsh-system-prompt@deepseek-ai/dsh-tools@deepseek-ai/dsh-typert-protocol@deepseek-ai/schemastery
用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动

README

dsh-vault — 用于 DeepSeek Harness 的加密凭据保险库

License: MIT
npm version
GitHub Release
npm downloads
GitHub issues
Listed: awesome-dsh-plugin
Listed: awesome-deepseek-harness

安全性与实现

- 零外部加密依赖:一切都构建在 Node 内置的 node:crypto 之上(AES-256-GCM 认证加密、scrypt 密钥派生、RFC 6238 TOTP)。
- 主密码:每个条目都使用通过 scrypt(master password, salt) 派生的 256 位密钥和 AES-256-GCM 加密。密钥从不落盘;解锁后缓存在进程内,重启时重新派生。
- 防篡改:GCM 认证标签加上固定明文验证信封——错误的主密码或被修改的密文会立即失败,绝不会返回乱码。
- 静态无明文:磁盘上的文档不包含明文凭据;每个条目使用独立的随机 nonce。
- 原子写入:复用 harness 的 writeFileAtomic + 文件锁;进程内写入串行化,跨进程写入者获取锁。
- 搜索绝不泄露:vault_search 仅返回摘要(id/title/kind/username/email/phone/host/port/url/tags)——绝不返回密码、密钥、令牌或 TOTP 密钥。完整凭据只能通过按 id 显式调用 vault_get 读取。

条目模型

每条记录都有一个 title、一个可选的 kind,以及以下字段的任意组合:

| 字段 | 描述 |
|---|---|
| kind | login(默认)/ ssh / api-key / secret / oauth / custom |
| username / email / phone | 账户身份 |
| password | 密码 |
| host / port | SSH 主机和端口(例如 db.internal / 2222) |
| privateKey | SSH 私钥(PEM) |
| apiKey | API 密钥 |
| secret | 通用密钥(客户端密钥、共享密钥……) |
| accessToken / refreshToken / expiresAt | OAuth 令牌对及过期时间(epoch 毫秒) |
| otpSecret | TOTP 密钥(裸 Base32 或 otpauth:// URI) |
| url / notes / tags | 元数据 |
| fields | 任意键/值对(例如 {"region": "us-east-1"}),可搜索 |

工具

| 工具 | 用途 |
|---|---|
| vault_add | 添加条目(可任意组合字段;空字符串/数组会被忽略) |
| vault_get | 按 id 读取完整条目(包括所有密钥) |
| vault_search | 搜索标题/分类/用户名/邮箱/电话/主机/端口/URL/备注/标签/自定义字段(包括数值/布尔/嵌套值;以空白分隔的词条按 OR 匹配);可选 createdAfter/createdBefore epoch 毫秒过滤器;返回不含密钥的摘要;limit 必须是 1–100 的整数 |
| vault_update | 按 id 更新字段(未提供的字段保留;空字符串会清除字段;title 可重命名;rotationDays: 0 清除轮换 = 永不轮换) |
| vault_compare | 逐字段比较两个条目(onlyA/onlyB/differ/equal)——仅字段名,绝不包含密钥值 |
| vault_rename | 一次调用重命名条目(vault_update 的快捷方式) |
| vault_delete | 软删除条目(将其移入回收站,磁盘上仍加密) |
| vault_restore / vault_purge / vault_restore_recent | 恢复已移入回收站的条目 / 彻底清除它 / 撤销上一次删除 |
| vault_lock / vault_unlock | 显式锁定保险库(清除内存中的密钥)/ 重新解锁 |
| vault_totp | 为存储的 otpSecret(或裸 Base32 / otpauth URI)生成当前 6 位验证码 |
| vault_generate_password | 生成强随机密码(长度/字符类别/分组)或易记口令(passphrase: true,EFF 风格词表,words/separator/wordDigits) |
| vault_strength | 零依赖密码强度估算(评分 0–100,弱/一般/强/非常强) |
| vault_password_history | 列出条目的历史密码(1Password/Bitwarden 风格,最新在前,最多 10 条;不含当前密码) |
| kind: card | 银行卡/信用卡条目:cardNumber/cardExpiry(MM/YY)/cardCvv/cardHolder;搜索摘要仅暴露有效期 + 持卡人(绝不暴露卡号或 CVV);Bitwarden JSON 导出映射为 card 项(类型 3,品牌自动推断) |
| vault_password_rollback | 将条目密码恢复到已存储的历史条目(当前密码会先归档,因此可逆) |
| vault_recovery_code / vault_verify_recovery / vault_recovery_status | 一次性保险库恢复码(1Password/Bitwarden 风格):32 字符代码仅显示一次,仅存储其 SHA-256 哈希;验证是否持有该代码;检查是否已设置 |
| vault_rekey | 就地升级保险库到新的 scrypt KDF 参数 |
| vault_backup | 带保留策略的时间戳加密备份;可选 note |
| vault_import_csv | 从 CSV 文件批量导入凭据(自定义列会成为字段;overwrite: true 会将字段合并到现有条目中,而不是重复创建) |
| vault_bulk_delete | 软删除匹配查询/类型/标签的条目或指定 id 的条目;需要 confirm: true(默认试运行);已移入回收站的条目可恢复 |
| vault_apply_tags | 对匹配查询的每个条目批量添加/移除/替换标签(支持试运行,不涉及机密) |
| vault_totp_uri | 为已存储或裸 TOTP 密钥构建 otpauth:// 配置 URI |
| vault_switch / vault_list | 按名称切换活动 vault / 列出可用 vault |
| vault_rotation | 报告已过期/需要轮换/即将过期的凭据;soonWindowDays(1-90,默认 7)调整即将到期的时间范围(不涉及机密) |
| vault_health | Vault 健康扫描:弱密码/重复使用密码、缺少 2FA、不安全的 http:// 站点,以及总体安全评分(0–100) |
| vault_watchtower | Watchtower 风格的逐条目风险分析(受 1Password/Bitwarden 启发):标记过短/弱密码、键盘序列、内嵌年份、常见密码、重复使用、http:// 站点、缺少 2FA、过期——并给出 0–100 评分和良好/警告/较差判定(不涉及机密);条目行显示 ⚠ 徽章 |
| vault_breach_check | 针对 Have I Been Pwned 的 Watchtower 风格泄露扫描(k-匿名:只有 SHA-1 前缀离开本机),并提供离线常见密码回退 |
| vault_integrity | 验证磁盘上的 vault 文件能否正确解密,并与内存中的存储匹配 |
| vault_merge | 将一个条目合并到另一个条目;keepSource: true 在合并后保留源条目 |
| vault_attach / vault_attachments / vault_attachment / vault_detach | 将文件附加到条目(私钥、证书、配置、恢复代码)——以 base64 形式存储在加密条目内部,静态加密;列出名称/大小、读取内容、移除 |
| vault_quick_add | 快速捕获(标题 + 一个机密),可选标签/备注 |
| vault_expiry | 设置/清除过期时间(expiresAt: 0 将其移除) |
| vault_stats | 概览计数,包括 trashCount(不涉及机密) |
| vault_verify | 验证单个条目或审计每个条目(all: true),检查每种类型的完整性、端口/过期时间合理性(不涉及机密) |
| vault_duplicates | 查找重复组:mode = both(默认)/ title / content(不涉及机密) |
| vault_report | 可打印的清单,包含过期/轮换列和统计页脚(不涉及机密) |
| vault_export / vault_import | 整个 vault 的可移植加密备份/迁移(使用单独的导出密码) |
| vault_backup / vault_backup_now | 带时间戳的加密备份,命名为 -backups-YYYY-MM-DD_HH-MM-SS-.json(所属 vault + 日期可见);保留策略会保留最新的 N 个 |
| vault_restore_backup | 从备份恢复:mode: "merge"(默认)将备份条目复制到当前 vault 中,使它们出现在条目列表中;mode: "replace" 会先创建安全快照,然后用备份覆盖整个 vault |
| vault_vault_rename / vault_vault_delete | 重命名命名保险库(文件移动,活动会话跟随)或永久删除一个(默认保险库受保护) |
| vault_match_url | 查找与 URL 匹配的登录条目(Bitwarden/1Password 风格:精确主机、子域、父域、路径前缀;www./端口规范化),带有 0–100 评分——绝不返回密码 |
| vault_fill | 查找与主机/URL/用户名/标题匹配的条目并返回其凭据 |
| vault_env | 将标记为 env 的条目(标签包含 env)渲染为 KEY=VALUE 行——参见环境导出 |
| vault_export_bitwarden / vault_import_bitwarden | Bitwarden/Vaultwarden JSON 互操作(完整字段映射,支持覆盖) |
| vault_import_bitwarden_encrypted | 解密受 Bitwarden 密码保护的 JSON 导出(PBKDF2/Argon2id + HKDF → AES-256-CBC + HMAC)并导入;传入导出密码短语 |
| vault_import_manager_csv | 通过表头自动检测的密码管理器 CSV:Bitwarden(login_uri/login_username/…)、1Password 8、Dashlane、NordPass、Keeper、LastPass(fav/grouping/extra);dryRun 预览 |
| vault_import_kdbx | KeePass KDBX:3.1 和 4.x,AES-KDF 或 Argon2(RFC 9106),AES-256-CBC 或 ChaCha20 载荷,支持密钥文件 |
| vault_export_1password | 将条目导出为 1Password 1PUX 归档(ZIP + export.data),以便导入 1Password 或在此重新导入;条目类别映射为登录 / 信用卡 / API 凭据 / 服务器 |
| vault_import_1password / vault_import_1pif | 1Password 1PUX(ZIP)和旧版 1PIF 文本导出 |
| vault_import_enpass | Enpass JSON 导出(文件夹 → 标签,类型化字段,TOTP) |
| vault_import_keepass_xml | KeePass 2.x XML 导出(明文或 *** 掩码值) |
| vault_import_chrome / vault_import_keychain | 从 Chrome 的 Login Data(macOS 钥匙串 / Linux 密钥环或 peanuts / Windows DPAPI)或 macOS 钥匙串导入密码(默认互联网密码 inet——实际支撑网站登录的那些——或通过 classes 使用通用 genp;会话缓存 + 预览,无提示骚扰);每个文件导入都支持 dryRun 预览 |
| vault_import_firefox | Firefox 配置文件导入(logins.json + key4.db,NSS 3DES / PBES2-AES,主密码感知) |
| vault_search_system | 在 Chrome / 钥匙串中搜索站点和用户名——绝不暴露密码 |
| vault_session_open | 在 URL 处打开一个真实的有头浏览器窗口,以便用户手动登录(密码、2FA、验证码)——这是为阻止嵌入的站点捕获登录状态的便携方式 |
| vault_session_collect | 收集打开的浏览器会话的每个 cookie(包括 HttpOnly)并将其保存为 cookie 条目 |
| vault_session_import | 从粘贴的 JSON(devtools 导出格式)或原始 Cookie 头字符串保存会话 cookie——无浏览器替代方案 |
| vault_session_import_file | 导入 Netscape cookie-jar 文件(curl -b / wget / 浏览器扩展导出;与 vault_session_export 写入的格式相同) |
| vault_session_list | 列出已保存的登录会话,包含 cookie 数量、已过期数量以及 7 天内即将过期的数量(不含具体值) |
| vault_session_export | 将已保存的会话导出为 Cookie 请求头值、Netscape cookie-jar 文件(curl -b)、原始 JSON(Playwright addCookies 格式),或可直接运行的 Playwright 代码片段 |
| vault_session_close | 关闭已打开的浏览器登录会话(已收集的 cookie 仍保留在 vault 中) |
| vault_session_prune | 从已保存的会话中移除已过期的 cookie(会话 cookie 会保留);preview: true 仅报告而不写入 |
| vault_copy | 将条目(包含密钥)复制到另一个指定名称的 vault |
| vault_templates | 内置 + 用户自定义模板(保存/列出/移除),KeePassXC 风格;内置模板现包含 Wi-Fi、Server、Database、Identity、Bank account、Card(受 1Password 启发) | 内置 + 用户自定义模板(保存/列出/移除),KeePassXC 风格 |

典型工作流:存储一个 SSH 凭据(kind: ssh + host/port/username/password 或 privateKey),然后让模型通过 vault_search 查找主机,再通过 vault_get 获取连接详情;保留 api-key/oauth 条目,用于 API 网关的访问令牌/刷新令牌轮换。

安装

dsh-vault 是一个 bundle(一个声明了 dsh.bundle 的包):一旦安装到某个 profile 中,它的 cordis.patch.yml 会自动插入 vault 插件行(通过包名 dsh-vault 引用;主密码通过 DSH_VAULT_PASSWORD 环境变量注入)。该包自带一个自包含的构建脚本——通过 git 安装时会自动编译 lib/。

以下四种安装路径均经过 端到端验证(安装 → 识别 bundle 层 → 插件激活并注册全部 7 个 vault_ 工具 → 真实的 vault_add/vault_get 往返 → 卸载后移除该层):

| 路径 | 命令 | 是否需要构建 | allowBuilds |
|---|---|---|---|
| npm | add dsh-vault | 否(预构建的 lib/) | 否 |
| GitHub | add github:Ox0400/dsh-vault#v0.1.1 | 是(prepare) | 是(首次运行) |
| 本地路径 | add /abs/path/to/dsh-vault | 否(链接到已构建的源码) | 否 |
| tarball | add ./dsh-vault-0.1.1.tgz | 否(预构建的 lib/) | 否 |

方案 1:从 npm 安装(最简单)

dsh plugin --profile web add dsh-vault

npm 包自带 预构建的 lib/ 产物——无需 allowBuilds,无需本地编译,安装即可使用。启动前设置主密码:

export DSH_VAULT_PASSWORD='your strong master password'

方案 2:从 GitHub 安装(固定 tag 或 commit)

dsh plugin --profile web add github:Ox0400/dsh-vault#v0.1.1

通过 git 安装获取的是 源码,而非已构建的产物,因此 prepare 脚本会在安装时构建 lib/。pnpm ≥10 默认会阻止 git 依赖运行构建脚本。经验证的流程如下:

1. 运行 add 命令——它会因 allowBuilds 错误而失败,并打印出需要允许的确切键(包含仓库 URL 的那一行,包括解析后的 commit 哈希):

allowBuilds:markdown
dsh-vault@https://codeload.github.com/Ox0400/dsh-vault/tar.gz/: true

2. 将该精确键追加到配置文件的 pnpm-workspace.yaml($DSH_HOME/profiles//pnpm-workspace.yaml)中:

yaml
packages:
- .
allowBuilds:
dsh-vault@https://codeload.github.com/Ox0400/dsh-vault/tar.gz/: true

3. 重新运行 add —— pnpm 现在会运行 prepare 脚本,构建 lib/,然后安装。

固定一个 tag/commit,这样后续上游推送就无法悄悄改变安装时运行的内容。请如实看待这项许可:它是在安装时在你的机器上执行该包代码的权限——只应授予你信任的来源。

选项 3:从本地路径安装
sh
dsh plugin --profile web add /absolute/path/to/dsh-vault

pnpm 会将检出目录链接到配置文件中;只要 lib/ 存在,该 bundle 就会被识别(如有需要,请先在检出目录中运行 pnpm build)。

选项 4:从 tarball 安装
sh
npm pack && dsh plugin --profile web add ./dsh-vault-0.1.1.tgz

该 tarball 附带预构建的 lib/ 产物,因此无需构建步骤或 allowBuilds。

dsh plugin --profile web remove dsh-vault 用于卸载(同时移除依赖和层)。

命令行

该插件将 vault 交给助手使用。捆绑的 dsh-vault 命令
将同一个 vault 交给 shell 和脚本使用,因此 skill 的子进程可以读取
密钥,而明文永远不会进入模型的上下文。

0. 首先:你实际能输入哪个命令?

在包安装之前,没有任何东西会提供 dsh-vault 二进制文件 ——
该插件是一个 Cordis bundle,而 dsh 没有插件子命令注册表(启动器
只解析自己的标志;dsh plugin … 只是转发给 pnpm,因此
dsh web exec … 会将其参数交给 web 应用,并以
error: too many arguments 失败)。在阅读示例之前,请先确定你属于哪一行:

| 你的环境 | 命令 |
|---|---|
| 源码检出(git clone + pnpm build) | pnpm vault —— 或 node lib/cli.js,或 ./lib/cli.js |
| 插件已安装到配置文件中 | pnpm dsh plugin --profile web exec dsh-vault |
| 全局安装(npm i -g dsh-vault) | dsh-vault |
| 未安装任何内容 | npx dsh-vault |
sh
源码检出 —— 就是本仓库,现在:
pnpm vault list

全局安装后(或通过 npx),相同的命令为:
dsh-vault list
npx dsh-vault list

下面的每个示例都写作 dsh-vault …;请替换为你所在行对应的形式
(在检出目录中为 pnpm vault …)。

1. env 的用途

get 获取一个值,且不需要 tag。dsh-vault env 用于另一种
情况:一个脚本需要多个密钥。它会将你标记为 env 的条目
打印为 shell 赋值语句,这样脚本就能自行读取它们:

$ dsh-vault env
DEMO_API_KEY='sk-demo-123'
OTHER_PASSWORD='pw-not-exported'

eval "$(dsh-vault env)" 会将这些赋值读入当前 shell ——
这是使用它的常见原因:
sh
eval "$(dsh-vault env)"          # KEY=VALUE 行会变成 shell 变量
echo "$DEMO_API_KEY"

有两点值得了解:

- 只有带有 env 标签的条目才会被导出。 如果没有条目带有该标签,你会看到
“no entries are tagged for environment export”;在 UI 中给某个条目打上标签(在
条目的 tags 字段中),或者用 vault_update { id, tags: ["env"] }。
- 名称由标题和字段派生而来(DASHSCOPE + apiKey →
DASHSCOPE_API_KEY),除非该条目设置了 envKeys —— 参见
环境导出。

名称 —— 只有三个,其中两个故意都是 env 这个词:

| 名称 | 它是什么 | 含义 |
|---|---|---|
| env | 一个条目标签 | dsh-vault env 导出哪些条目;没有它就不会导出任何内容 |
| env | 该命令 | 只打印带有该标签的条目 |
| envKeys | 一个条目字段(可选) | 固定确切的名称,例如 ["DASHSCOPE_API_KEY"];旧的单数形式 envKey 可作为单元素简写被接受 |

没有其他东西叫 env:list --json / show 会报告 envKeys(条目导出的名称
—— 即 get 接受的名称)和 envTagged(env 是否包含它)。

2. 命令

dsh-vault list                             # 分组显示:env 导出的内容 vs 其余内容
Exported by env (tag "env") — 1 entry:
a1b2c3d4-…  api-key   DASHSCOPE        → DASHSCOPE_API_KEY
Not exported (no "env" tag) — 1 entry; get  still works for it:
9f8e7d6c-…  api-key   Example Billing  → EXAMPLE_BILLING_API_KEY
dsh-vault get my-entry                     # 条目的主密钥,仅输出到 stdout
dsh-vault get my-entry --field apiKey      # 一个指定字段
dsh-vault get my-entry --mask              # 确认它存在但不打印它
dsh-vault show my-entry                    # 以 JSON 形式显示非密钥元数据
dsh-vault env                              # 带 env 标签的条目,格式为 KEY=VALUE
dsh-vault env --mask                       # 人类可读视图,两个部分均为 KEY=VALUE:
exported items
NPM_REGISTRY_API_KEY=npm_**
unexported items
EXAMPLE_BILLING_API_KEY=***
dsh-vault export-env .env                  # ……或者将它们写入一个 0600 文件
dsh-vault verify                           # 检查主密码,stdout 上不输出任何内容

密钥输出到 stdout,其他所有内容(进度、错误)输出到 stderr,因此
$(dsh-vault get …) 和管道都能正常工作。退出码:0 正常,1 运行时
错误,2 用法错误。

3. Shell 引号:不是 export $(…)

eval "$(dsh-vault env)" 是正确的;export $(dsh-vault env) 是错误的。命令
替换会按空白拆分,并且不会去掉 CLI 输出的引号,因此包含空格的值会被拆成
错误的单词,而且每个值都会保留其字面引号:

$ export $(dsh-vault env); echo "$WITH_SPACE"
['pass]                     # 在空格处拆分
bash: export: here': not a valid identifier
$ eval "$(dsh-vault env)"; echo "$WITH_SPACE"
[pass word here]            # 按预期读取
在脚本中,优先使用文件形式——完全不用 eval:

dsh-vault export-env .env && set -a && . ./.env && set +a

4. 主密码

--password-stdin,然后是 $DSH_VAULT_MASTER_PASSWORD(或 $DSH_VAULT_PASSWORD),
再然后是一个隐藏你所输入内容的交互式提示(终端会切换到
原始模式;可用 tests/e2e/cli-prompt.mjs 验证)。它不会从插件的配置文件中读取,因此
CLI 从不依赖(也不会泄露)profile 补丁中所保存的任何内容:

DSH_VAULT_MASTER_PASSWORD=… pnpm vault list
printf '%s\n' "$PASSWORD" | pnpm vault list --password-stdin

5. 安装细节

源码检出:

git clone git@github.com:Ox0400/dsh-vault.git && cd dsh-vault
npm install && npm run build            # builds lib/, including executable lib/cli.js

pnpm vault list                         # the repo's own entry point (package.json script)
node lib/cli.js list                    # same thing, spelled out
./lib/cli.js list                       # the file is executable too
npm link                                # …or put a real dsh-vault on PATH

要针对某个 profile 开发插件,你还需要把检出的代码链接到该
profile 中,并添加一个插入它的补丁层(本仓库通常就是这样开发的);CLI 完全不需要这些——它直接读取 vault 文件。手动
链接的插件没有 .bin/dsh-vault 垫片,因此 pnpm … exec 会报告
Command "dsh-vault" not found,除非你把它作为依赖安装
(pnpm dsh plugin --profile web add dsh-vault)或手动创建该垫片:

ln -sf ../dsh-vault/lib/cli.js ~/.dsh/profiles/web/node_modules/.bin/dsh-vault

npm 安装:

pnpm dsh plugin --profile web add dsh-vault          # into a profile (plugin + CLI together)
pnpm dsh plugin --profile web exec dsh-vault list    # --profile is required

npm i -g dsh-vault && dsh-vault list                 # globally
npx dsh-vault list                                   # or not at all

读取类命令(list、get、env、show、verify、export-env)仅
依赖 Node,这就是全局安装和 npx 形式能奏效的原因。只有写入
vault 才需要 harness 运行时,而插件始终拥有它。

关于 profile 方式还有两点注意事项:它的 .bin 垫片可能会被之后的
pnpm install 清除,而且 pnpm dsh plugin --profile web add dsh-vault 会根据包的 dsh.bundle 声明来协调
dsh.profile.bundles——如果你自己的
补丁层也插入了该插件,那就会把它挂载两次,所以请先移除补丁
行。

泄露检查的隐私性

vault_breach_check(以及安全页面)可以对照 Have I
Been Pwned 检查密码。只有一样东西会离开这台机器:

GET https://api.pwnedpasswords.com/range/
Add-Padding: true

响应会列出该桶中的每个后缀(数百个哈希),而匹配
是在本地计算的——完整哈希、密码以及它所属的条目
绝不离开。已在捆绑的常见密码列表中的密码会离线应答,并且完全不产生任何请求;对同一前缀的重复查询会在内存中缓存一小时。

k-匿名不能隐藏的内容,直白地说:

- 五字符前缀(20 位,约 100 万个桶中的一个)会发送到 Cloudflare,连同你的 IP 一起;
- 能够猜测候选密码的观察者可以计算每个候选密码的前缀,并查看你是否查询过该桶——这是该协议的已知局限,而不是标头能修复的问题;
- Add-Padding 只能消除响应大小信号(没有它,某个桶的响应长度会与密码的常见程度相关)。

若要把连前缀都留在你的机器上,请传入 online: false——这样检查只使用离线列表,而离线列表要小得多,因此请把它当作筛查辅助手段,而不是最终判定。

强度指示器

每个条目行都会在其标题后显示一个三星指示器——☆☆☆ = 0 分,★★★ = 满分——分为六个半星档位:

强度指示器:七种状态

半星是真正的半填充星,而不是旁边放一个 ½:同一组三个字形的彩色副本会按百分比裁剪,而 ★/☆ 具有相同的步进宽度,因此裁剪会精确落在星形边界上。

| 分数 | 填充星数 | 等级 |
|---|---|---|
| 0–8 | 0 | 弱 |
| 9–24 | ½ | 弱 |
| 25–41 | 1 | 弱 |
| 42–58 | 1½ | 一般 |
| 59–74 | 2 | 一般 |
| 75–91 | 2½ | 强 |
| 92–100 | 3 | 非常强 |

悬停在其上会显示确切分数和判定。分数是在宿主端计算的(列表永远不会收到机密),并且涵盖条目的密码或卡 PIN;机器生成的 API 密钥和私钥有意不评分,因此并非每个密钥都会处于满分。

环境变量导出

标记为 env 的条目可以物化为 KEY=VALUE 行(vault_env、vault_export_env),并且其名称遵循每个工具链所期望的字段名:

| 条目 | 导出的键 |
|---|---|
| 标题 DASHSCOPE、apiKey | DASHSCOPE_API_KEY |
| 标题 DASHSCOPE、prefix: APP_ | APP_DASHSCOPE_API_KEY |
| envKey: "TAVILY_TOKEN"、accessToken | TAVILY_TOKEN |
| ……同一条目的 refreshToken / fields.scope | TAVILY_TOKEN_REFRESH_TOKEN / TAVILY_TOKEN_SCOPE |

- 字段后缀遵循供应商标准:apiKey → API_KEY、accessToken →
ACCESS_TOKEN、refreshToken → REFRESH_TOKEN、privateKey → PRIVATE_KEY、
password → PASSWORD、cardNumber → CARD_NUMBER。
- 当派生名称不是你的脚本所期望的名称时,可设置条目的环境变量名(可选字段 envKeys,也可通过
vault_add/vault_update 设置,或在编辑器中用逗号分隔)。它们是按位置对应的,并且会原样使用(无前缀、无标题):

| envKeys | 导出 |
|---|---|
| ["DASHSCOPE_API_KEY"] | DASHSCOPE_API_KEY=apiKey |
| ["GOOGLE_ACCESS_TOKEN", "GOOGLE_REFRESH_TOKEN"] | ...=accessToken、...=refreshToken |
| ["MY_KEY"] 用于包含 3 个密钥的条目 | MY_KEY、MY_KEY_REFRESH_TOKEN、MY_KEY_SCOPE |

每个名称必须是 POSIX 标识符([A-Za-z_][A-Za-z0-9_]),最多 8 个,
且不能重复。envKey(单个字符串)仍可作为
单元素简写被接受,并在写入时合并到 envKeys 中。
- 自定义字段也会被导出,格式为 _。

升级提示:在
1.10.64 中,密钥从 DASHSCOPE_APIKEY 改为 DASHSCOPE_API_KEY,以符合供应商惯例。如果某个脚本依赖旧拼写,
可在条目上设置 envKey 来固定确切的名称。

工具配置文件

该插件附带 110+ 个模型工具,但默认只注册 11 个核心工具(vault_list/search/get/add/update/delete/fill/clipboard/totp/generate_password/strength),以保持模型的工具目录小巧且低成本。

在设置 → 凭据 → 权限 → 模型工具中切换配置文件——它会立即生效(无需重启),并按保管库持久化:

| 配置文件 | 注册内容 |
|---|---|
| Basic(默认) | 仅核心——日常使用 |
| Standard | + 管理:收藏、标签、图标、过期/轮换、健康检查、重复项/合并、附件、模板、环境变量掩码 |
| Full | 全部内容,包括批量导入/导出、浏览器会话、备份和保管库文件操作 |
| Custom… | 核心 + 以下任意项:管理 / 导入导出 / 浏览器会话 / 备份与文件 |

tools: basic|standard|full|custom 也可以在插件配置中设置;UI 选择优先,并存储在 /access.json 中。

配置

[!WARNING] 安全:切勿将主密码以明文形式存放
配置文件补丁(cordis.patch.yml / cordis.yml)是一种很容易被提交到 git、截图或记录到日志中的配置文件——因此,一行明文的
masterPassword: 会将密钥泄露给你整个加密保管库。请始终使用
masterPasswordEnv,并将真实密码导出到进程/shell
环境中(例如 export DSH_VAULT_PASSWORD='…')。有关凭据处理插件的证据优先检查清单,请参阅
社区插件审计手册。

✗ 不要这样做——在配置文件中使用明文主密码
- id: vault
name: dsh-vault
config:
masterPassword: 'my-secret'

✓ 应该这样做——引用环境变量;并将文件本身权限设为 0600
- id: vault
name: dsh-vault
config:
masterPasswordEnv: DSH_VAULT_PASSWORD

| 选项 | 描述 |
|---|---|
| masterPassword | 内联主密码(会出现在 cordis.yml 中;不推荐) |
| masterPasswordEnv | 保存主密码的环境变量名称(推荐) |
| path | 保管库文件路径;默认为 $DSH_HOME/vault/default.json |
| name | 默认路径的保管库名称(例如 name: work → $DSH_HOME/vault/work.json) |
| accessMode | 模型工具的访问策略。三种状态:readonly(工具和 UI 上的变更操作被拒绝)、ask(默认——读取自由,每次添加/更新/删除都经过 harness 审批通道,以便用户确认每次写入)、或 auto(自动读写,无需每次调用提示)。设置 UI 提供这一确切的三选一选项,并将其持久化到 /access.json。 |
| autoCapture | false(默认)。当为 true 时,系统提示会指示模型检测对话中共享的凭据,并根据用户偏好,主动提出用 vault_add 保存它们。 |
| lockTimeoutSeconds | 自动锁定:在这么多秒无活动后,保险库会重新锁定(密钥被清除),每次读/写都需要 vault_unlock。0/缺省则禁用。 |
| exportPasswordEnv | 保存 vault_export/vault_import 导出/导入密码的环境变量(切勿将其作为模型参数传递)。 |
| backupRetention | 保留多少个加密备份(默认 10);vault_backup 会清理较旧的副本。 |

示例:

- id: vault
name: dsh-vault
config:
masterPasswordEnv: DSH_VAULT_PASSWORD
accessMode: ask
autoCapture: true

当 autoCapture: true 时,当你在聊天中共享凭据(例如“我的 npm token 是 npm_…”),助手会主动提出存储它;在你同意后,它会立即调用 vault_add。当 autoCapture 关闭时,只有你明确要求时才会保存凭据。设置 UI 显示当前模式(只读 / 写入前询问 / 自动读写),并带有用于切换的下拉菜单、一个自动捕获开关(检测聊天中共享的凭据 → 主动提出保存)、一个类型过滤器、一个健康与轮换摘要、一个回收站视图,以及带显示/隐藏切换的掩码密钥字段。

保险库在首次使用工具时自动创建;每次启动时都会用主密码重新解锁。忘记主密码 = 永久数据丢失(没有后门——这是设计使然)。

开发

在本地克隆并开发:

git clone git@github.com:Ox0400/dsh-vault.git
cd dsh-vault
pnpm install    # installs devDependencies (typescript/tsdown/vitest, …)
pnpm build      # builds host lib/.js and the browser bundle lib/client.js
pnpm test       # runs the 420 vitest tests

测试需要 harness 对等包,例如 dsh-llm/dsh-system-prompt;在 harness monorepo 内部,这些包通过工作区链接解析。

常用命令:

pnpm test          # unit + integration tests (vitest, 420)
pnpm typecheck     # tsc -p tsconfig.json --noEmit
pnpm build         # = build:host (tsc) + build:client (tsdown)
npm pack           # optional: tarball for dsh plugin add ./dsh-vault-0.1.1.tgz

全部 420 个测试均通过(crypto / TOTP / 密码生成 / 存储 CRUD / 网关 / 集成)。

浏览器检查针对真实的 dsh web 运行,而不是 vitest,并且其中每一项
都拒绝在默认保险库上操作:

node tests/e2e/theme-check.mjs      # dual-theme tokens, ring track, attach row
node tests/e2e/polish-check.mjs     # 空状态文案、相对时间悬停提示
node tests/e2e/contrast-audit.mjs   # 对全部八个标签页、两种主题进行 WCAG 扫描

关于安全规则,以及会让对比度审计说谎的两个陷阱(序列化的 color(srgb …) 值,以及 opacity 被计入颜色),请参见 tests/e2e/README.md。

让凭据远离公开内容

本仓库中的一切都是公开的——npm tarball、GitHub 发布、issue 和讨论帖。发布前,pnpm scan:secrets 会检查工作树、已跟踪文件以及提交信息中任何看起来像凭据的内容,而 pnpm scan:public 还会额外检查所有已发布的 release 和评论。本地这一半也会在 pnpm test 中运行,因此已提交的密钥会让 CI 失败,而不是被发布出去。

主题化

UI 读取宿主的设计令牌,而不是硬编码颜色。一个本地语义层映射到真正的 --dsw-alias- 命名空间,并带有字面量回退值,因此页面在 DeepSeek Harness 之外仍能渲染:
css
--v-text: var(--dsw-alias-label-primary, #1f2328);
--v-border: var(--dsw-alias-border-l2, #d9d9d9);
--v-success-text: color-mix(in srgb, var(--v-success) 55%, var(--v-text));

由于这些别名会随 body[data-ds-dark-theme] 翻转,浅色和深色会自动跟随宿主——没有第二份样式表,也没有主题 prop。

这一层存在的目的,是强制执行两条规则:

- 绝不要将 state--primary 用作正文文本。 这些令牌是为填充和图标调校的:在白色背景上,它们测得 2.28:1(success)和 2.15:1(warn),远低于 WCAG AA。--v-*-text 变体会将它们向主题自身的文本颜色混合,因此一次声明即可在浅色下变深、在深色下变浅(浅色 5.8/5.6/7.5:1,深色 12+/11+/6.5:1)。
- 绝不要用 opacity 来调暗文本。 opacity: .8 会把 5.8:1 的颜色变成 3.9:1。请用令牌(--v-text-2)来表达“次要”,而不是用透明度。

tests/e2e/contrast-audit.mjs 会在两种主题下对每个标签页验证这两条规则。

打包与发布

本包是一个标准的 npm bundle:

- dsh.bundle.patch → cordis.patch.yml(当某个 profile 列出此 bundle 时自动应用的层)
- dsh.client → 浏览器端声明(exports["./client"] 指向 lib/client.js)
- prepare 脚本 → 在 git 安装时进行自包含构建(tsc 宿主 + tsdown 客户端)
- 运行时依赖全部是 peerDependencies(由宿主 harness 提供——不会产生重复实例)

分发方式:
sh
npm pack                  # tarball → dsh plugin add ./dsh-vault-0.1.1.tgz
npm publish --access public   # registry → dsh plugin add dsh-vault

安全边界与已知限制

- 保险库的强度受主密码强度限制;请使用 ≥ 16 个字符的高熵密码。
- scrypt 成本参数(N=32768, r=8, p=1)会持久化在文档中,并可在未来版本中提高;旧文档仍可解密。
- 明文凭据仅存在于进程内存中以及显式 vault_get 读取期间;vault_search/vault_update 的输出绝不包含密码、密钥或令牌。由 vault_get 返回的机密会进入该工具调用的结果(模型上下文)——调用方应避免在对话中重复它们。
- 此插件面向单机 / 个人部署;团队共享的 vault 不在范围内。

收录于

- awesome-dsh-plugin — 官方精选目录(Security & Safety 部分)
- awesome-deepseek-harness (Dominic789654) — 社区目录(Security 部分)

待维护者审核的提交:Anil-matcha/awesome-dsh-plugin #127 · 0xsline/awesome-deepseek-harness #563 · dsh-handbook #65

上游仓库有新提交时邮件通知你(每天最多一封,无更新不打扰),随时一键退订。

💬 加入 DPharness 群聊

插件用法、部署报错、新插件第一时间同步——群里问,比一个人翻文档快。

点击加入 QQ 群
DPharness 群聊二维码,手机 QQ 扫码进群
扫码进群