dsh-vault 1.10.74 → 1.10.75

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README-zh.md CHANGED
@@ -27,7 +27,7 @@ dsh-vault 是一个面向 DeepSeek Harness 的安全加密插件:把你在使
27
27
 
28
28
  | 字段 | 说明 |
29
29
  |---|---|
30
- | `kind` | `login`(默认)/ `ssh` / `api-key` / `secret` / `oauth` / `custom` |
30
+ | `kind` | `login`(默认)/ `ssh` / `api-key` / `secret` / `oauth` / `cookie` / `card` / `custom` |
31
31
  | `username` / `email` / `phone` | 账号身份 |
32
32
  | `password` | 密码 |
33
33
  | `host` / `port` | SSH 主机与端口(如 `db.internal` / `2222`) |
@@ -37,35 +37,46 @@ dsh-vault 是一个面向 DeepSeek Harness 的安全加密插件:把你在使
37
37
  | `accessToken` / `refreshToken` / `expiresAt` | OAuth 令牌对与过期时间(epoch millis) |
38
38
  | `otpSecret` | TOTP 密钥(Base32 或 otpauth:// URI) |
39
39
  | `url` / `notes` / `tags` | 元信息 |
40
+
41
+ 其中两种 kind 有各自的形状:`cookie` 条目保存捕获的浏览器会话;`card` 条目保存 `cardNumber` / `cardExpiry`(MM/YY)/ `cardCvv` / `cardHolder` —— 检索摘要只暴露到期日与持卡人,绝不给卡号与 CVV;导出 Bitwarden JSON 时映射为 `card` 项(type 3,品牌自动推断)。
40
42
  | `fields` | 任意附加键值(如 `{"region": "us-east-1"}`),可检索 |
41
43
 
42
44
  ## 工具
43
45
 
44
- | 工具 | 作用 |
46
+ 共 113 个工具,分五组。**基础**是默认安装就会注册的;其余通过[工具分级](#工具分级工具集)按需开启(设置 → 凭据库 → 权限 → 模型工具集)。
47
+
48
+ ### 基础(默认注册) — 11
49
+
50
+ 共 11 个工具。下面各组都需按需开启。
51
+
52
+ | 工具 | 说明 |
45
53
  |---|---|
46
- | `vault_add` | 新增条目(上述字段任意组合;空字符串/空数组字段会被忽略) |
47
- | `vault_get` | 按 id 读取完整条目(含全部密钥) |
54
+ | `vault_list` | 列出保险库目录下可用的保险库(一个 .json 一个,排除 access/meta/导出等旁车文件) |
48
55
  | `vault_search` | 跨标题/分类/用户名/邮箱/手机/主机/端口/URL/备注/标签/自定义字段(含数字/布尔/嵌套值;空格分隔多词 OR 命中)检索;可选 `createdAfter`/`createdBefore` 毫秒时间戳过滤;返回无密摘要;`limit` 须为 1–100 的整数 |
56
+ | `vault_get` | 按 id 读取完整条目(含全部密钥) |
57
+ | `vault_add` | 新增条目(上述字段任意组合;空字符串/空数组字段会被忽略) |
49
58
  | `vault_update` | 按 id 更新字段(未提供的字段保留;空字符串清除该字段;`title` 可改名;`rotationDays: 0` 清除轮换 = 永不轮换) |
50
- | `vault_compare` | 逐字段比较两个条目(`onlyA`/`onlyB`/`differ`/`equal`)——只返回字段名,绝不返回密钥值 |
51
- | `vault_rename` | 一次调用即可重命名条目(`vault_update` 的快捷方式) |
52
59
  | `vault_delete` | 软删除条目(移入回收站,磁盘上仍加密保留) |
53
- | `vault_restore` / `vault_purge` / `vault_restore_recent` | 从回收站恢复 / 永久删除 / 撤销最近一次删除 |
54
- | `vault_lock` / `vault_unlock` | 显式锁定保险库(清空内存密钥)/ 重新解锁 |
60
+ | `vault_fill` | 按 host/URL/用户名/标题匹配条目并返回其凭据 |
61
+ | `vault_clipboard` | 取出某条目某个字段的值用于直接复制(用户名/密码/apiKey 等) |
55
62
  | `vault_totp` | 为存储的 otpSecret(或直接传入的 Base32/otpauth URI)生成当前 6 位动态验证码 |
56
63
  | `vault_generate_password` | 生成强随机密码(长度/字符集/分组可选)**或易记口令短语**(`passphrase: true`,EFF 词表,`words`/`separator`/`wordDigits`) |
57
64
  | `vault_strength` | 零依赖密码强度评估(0–100 分,weak/fair/strong/very strong) |
65
+
66
+ ### 管理(标准档及以上) — 53
67
+
68
+ 收藏、标签、活动历史、健康检查、模板、附件,以及卡与 2FA 的细节。
69
+
70
+ | 工具 | 说明 |
71
+ |---|---|
72
+ | `vault_compare` | 逐字段比较两个条目(`onlyA`/`onlyB`/`differ`/`equal`)——只返回字段名,绝不返回密钥值 |
73
+ | `vault_rename` | 一次调用即可重命名条目(`vault_update` 的快捷方式) |
74
+ | `vault_restore` / `vault_purge` / `vault_restore_recent` | 从回收站恢复 / 永久删除 / 撤销最近一次删除 |
75
+ | `vault_lock` / `vault_unlock` | 显式锁定保险库(清空内存密钥)/ 重新解锁 |
58
76
  | `vault_password_history` | 列出条目的历史密码(1Password/Bitwarden 风格,最新在前,上限 10 条;不含当前密码) |
59
- | `kind: card` | 银行卡/信用卡条目:`cardNumber`/`cardExpiry`(MM/YY)/`cardCvv`/`cardHolder`;搜索摘要只暴露有效期和持卡人(绝不显示卡号和 CVV);Bitwarden JSON 导出映射为 card 条目(type 3,自动识别卡品牌) |
60
77
  | `vault_password_rollback` | 将条目密码回滚到某条历史记录(当前密码先归档,可逆) |
61
- | `vault_recovery_code` / `vault_verify_recovery` / `vault_recovery_status` | 一次性保险库恢复码(1Password/Bitwarden 风格):32 位代码仅显示一次,只保存其 SHA-256 哈希;可验证代码持有;查询是否已设置 |
62
- | `vault_rekey` | 原地升级 scrypt KDF 参数并重加密 |
63
- | `vault_backup` | 带时间戳的加密备份,支持保留策略:超过 `maxBackups`(默认 10)的旧备份自动清理 |
64
- | `vault_import_csv` | 从 CSV 批量导入凭据(自定义列变为 fields;`overwrite: true` 合并字段到已有条目,不再产生重复) |
65
- | `vault_bulk_delete` | 按 query/kind/tag 或显式 ids 批量软删除条目;需 `confirm: true`(默认仅试运行);回收站可恢复 |
66
78
  | `vault_apply_tags` | 按查询批量增/删/替换条目标签(支持 dry-run,不含密钥) |
67
79
  | `vault_totp_uri` | 为存储的或裸 TOTP 密钥生成 otpauth:// 配置 URI |
68
- | `vault_switch` / `vault_list` | 按名称切换当前保险库 / 列出可用保险库 |
69
80
  | `vault_rotation` | 报告已过期 / 待轮换 / 即将过期的凭据;`soonWindowDays`(1-90,默认 7)调整即将窗口(不含密钥) |
70
81
  | `vault_health` | 保险库健康扫描:弱密码/复用凭据、未启用 2FA、不安全的 http:// 站点,以及整体安全评分(0–100) |
71
82
  | `vault_watchtower` | 每个条目的风险分析(借鉴 1Password Watchtower / Bitwarden):标记弱密码、键盘序列、嵌入年份、常见密码、跨条目复用、http 站点、缺 2FA、过期——带 0–100 评分与 good/warn/poor 判定(不含机密);条目行显示 ⚠ 徽标 |
@@ -79,13 +90,42 @@ dsh-vault 是一个面向 DeepSeek Harness 的安全加密插件:把你在使
79
90
  | `vault_verify` | 校验单个条目或审计全部条目(`all: true`):按 kind 检查完整性、端口/过期合理性(不含密钥) |
80
91
  | `vault_duplicates` | 查找重复分组:`mode` = `both`(默认)/ `title` / `content`(不含密钥) |
81
92
  | `vault_report` | 可打印清单,含到期/轮换列与统计页脚(不含密钥) |
82
- | `vault_export` / `vault_import` | 整库加密备份/迁移(独立导出密码) |
83
- | `vault_backup` / `vault_backup_now` | 时间戳加密备份,文件名 `<库名>-backups-YYYY-MM-DD_HH-MM-SS-<hex>.json`(库名+日期一目了然);自动保留最近 N 份 |
84
- | `vault_restore_backup` | 从备份还原:`mode: "merge"`(默认)把备份条目复制进当前库,出现在条目列表;`mode: "replace"` 整体覆盖(先写安全快照) |
85
- | `vault_vault_rename` / `vault_vault_delete` | 重命名命名库(文件移动,当前会话跟随)或永久删除(default 库受保护) |
86
93
  | `vault_match_url` | 按 URL 查找匹配的登录条目(Bitwarden/1Password 风格:精确主机、子域、父域、路径前缀;www./端口归一化),带 0–100 评分——绝不返回密码 |
87
- | `vault_fill` | 按 host/URL/用户名/标题匹配条目并返回其凭据 |
88
94
  | `vault_env` | 把标记 env 的条目(tags 含 `env`)渲染为 `KEY=VALUE` 行 —— 见[环境变量导出](#环境变量导出) |
95
+ | `vault_copy` | 复制条目(含密钥)到另一个命名保险库 |
96
+ | `vault_templates` | 内建 + 用户自定义模板(save/list/remove,KeePassXC 风格);内建模板新增 Wi-Fi、服务器、数据库、身份、银行账户、银行卡(借鉴 1Password) |
97
+ | `vault_notes` | 追加或整体替换条目的自由备注(等价于一次 `vault_update`) |
98
+ | `vault_changes` | 列出某个时间窗内(默认 24 小时)的库内活动:新增/更新/软删除,最新在前 |
99
+ | `vault_find` | 模糊查找:忽略大小写、标点与空白,所以 `gh` 也能命中 `GitHub` |
100
+ | `vault_mask` | 把任意文本里像凭据的部分打码(API key、token、密码、私钥),便于安全地记录或引用 |
101
+ | `vault_history` | 本进程内的近期活动,最新在前:写操作(增/改/删/恢复/清空/合并/回滚)与读操作(读取、验证码) |
102
+ | `vault_recent` | 列出最近新增或更新的条目(最新在前),只含非敏感摘要 |
103
+ | `vault_pin` | 收藏(置顶)条目,使其在搜索与列表中排在最前 |
104
+ | `vault_unpin` | 取消收藏(移除 favorite 标记) |
105
+ | `vault_tags` | 列出全库用到的所有标签及每个标签下的条目数 |
106
+ | `vault_generate_username` | 生成随机用户名或匿名邮箱建议 |
107
+ | `vault_rotate_password` | 生成新的强密码、写入条目,并把新值返回给调用方交给目标服务 |
108
+ | `vault_touch` | 把条目标记为"最近使用"(只更新 updatedAt,不改内容) |
109
+ | `vault_note_secret` | 用一个自动生成的标题存一条单独的密钥(临时记一条,不必先想标题)|
110
+ | `vault_search_advanced` | 多条件组合搜索:标题子串、用户名/邮箱子串、kind、标签、创建时间区间、仅收藏 |
111
+ | `vault_count` | 返回活跃条目数量(可按 kind / 标签过滤) |
112
+ | `vault_set_icon` | 设置条目的 UI 图标(emoji)与强调色 |
113
+ | `vault_describe` | 用自然语言描述一条目(kind、身份、主机/URL、标签、到期),不泄露任何密钥 |
114
+ | `vault_last_modified` | 按最后修改时间列出条目,最新在前 |
115
+ | `vault_has` | 快速判断库里是否存在匹配的凭据(标题/用户名/主机子串;`exact` 时按标题精确匹配) |
116
+ | `vault_autofill_check` | 判断库里是否有可用于某 URL/主机的凭据:返回最佳匹配条目(只给用户名/邮箱,绝不给密钥),或明确"没有" |
117
+ | `vault_undelete_all` | 把回收站里的条目全部恢复 |
118
+ | `vault_get_many` | 按 id 批量读取多个条目,且只返回请求的字段 |
119
+
120
+ ### 导入导出(完整档,或自定义 → 导入导出) — 27
121
+
122
+ 与其它密码管理器之间的进出、批量操作,以及 env/CSV/1Password/Bitwarden/KeePass/pass 互转。
123
+
124
+ | 工具 | 说明 |
125
+ |---|---|
126
+ | `vault_import_csv` | 从 CSV 批量导入凭据(自定义列变为 fields;`overwrite: true` 合并字段到已有条目,不再产生重复) |
127
+ | `vault_bulk_delete` | 按 query/kind/tag 或显式 ids 批量软删除条目;需 `confirm: true`(默认仅试运行);回收站可恢复 |
128
+ | `vault_export` / `vault_import` | 整库加密备份/迁移(独立导出密码) |
89
129
  | `vault_export_bitwarden` / `vault_import_bitwarden` | Bitwarden/Vaultwarden JSON 互通(完整字段映射,支持覆盖) |
90
130
  | `vault_import_bitwarden_encrypted` | 解密 Bitwarden 口令保护 JSON 导出(PBKDF2/Argon2id + HKDF → AES-256-CBC + HMAC)并导入,需提供导出口令 |
91
131
  | `vault_import_manager_csv` | 密码管理器 CSV 自动识别表头:Bitwarden(login_uri/login_username/…)、1Password 8、Dashlane、NordPass、Keeper、LastPass(fav/grouping/extra);支持 dryRun 预览 |
@@ -96,8 +136,24 @@ dsh-vault 是一个面向 DeepSeek Harness 的安全加密插件:把你在使
96
136
  | `vault_import_keepass_xml` | KeePass 2.x XML 导出(明文或 ****** 掩码值) |
97
137
  | `vault_import_chrome` / `vault_import_keychain` | 从 Chrome Login Data(macOS 钥匙串 / Linux 钥匙环或 peanuts / Windows DPAPI)或 macOS 钥匙串导入密码(默认只读互联网密码 `inet`——真正用于网站登录的条目,`classes: ["genp"]` 可改读通用密码;会话缓存 + 预览,避免授权弹窗轰炸);所有文件导入均支持 dryRun 预览 |
98
138
  | `vault_import_firefox` | Firefox 配置导入(logins.json + key4.db,NSS 3DES / PBES2-AES,支持主密码) |
99
- | `vault_search_system` | 在 Chrome / 钥匙串中搜索站点与用户名——绝不暴露密码 |
100
- | `vault_session_open` | 在真实浏览器窗口中打开指定网址,供用户手动登录(密码、二次验证、验证码)——对禁止嵌入的网站也能捕获登录态(需要可选的 `playwright-core`)|
139
+ | `vault_export_totp` | 列出所有带 TOTP 密钥的条目及其标题与签发方标签 |
140
+ | `vault_bulk_export` | 把**全部**条目(含密钥)导出为 JSON 文件,用于审计或迁移 |
141
+ | `vault_export_browser` | 按浏览器密码管理器 CSV 格式导出登录条目(name,url,username,password) |
142
+ | `vault_migrate_keepass` | 按 KeePass 2.x 导入 CSV 格式导出(Group,Title,Username,Password,URL,Notes) |
143
+ | `vault_export_keepass_xml` | 导出为 KeePassXC 兼容的 XML 文档(KeePass 2.x schema) |
144
+ | `vault_import_browser` | 导入浏览器密码管理器 CSV(name,url,username,password,Chrome/Firefox/Edge 导出格式) |
145
+ | `vault_export_wallet` | 导出为 `pass`(标准 Unix 密码管理器)兼容的目录树:一条目一文件,首行是密码 |
146
+ | `vault_import_wallet` | 从 `pass` 目录树导入:每个 .gpg(或明文)文件成为一个条目,文件名即标题,首行是密码 |
147
+ | `vault_export_env` | 把带 `env` 标签的条目写成 .env 文件(KEY=VALUE,值做 shell 引号处理) |
148
+ | `vault_export_csv` | 把条目导出为 CSV(与 `vault_import_csv` 同格式),可按 kind 过滤 |
149
+
150
+ ### 浏览器会话(完整档,或自定义 → 浏览器会话) — 8
151
+
152
+ 捕获与复用 cookie 会话;需要可选的 `playwright-core`。
153
+
154
+ | 工具 | 说明 |
155
+ |---|---|
156
+ | `vault_session_open` | 在真实浏览器窗口中打开指定网址,供用户手动登录(密码、二次验证、验证码)——对禁止嵌入的网站也能捕获登录态(需要可选的 `playwright-core`) |
101
157
  | `vault_session_collect` | 收集已打开浏览器会话的全部 cookie(含 HttpOnly),保存为 `cookie` 条目 |
102
158
  | `vault_session_import` | 从粘贴的 JSON cookie 数组(开发者工具导出格式)或原始 `Cookie` 头字符串保存会话 cookie——无需浏览器的替代方案 |
103
159
  | `vault_session_import_file` | 导入 Netscape cookie-jar 文件(curl `-b` / wget / 浏览器扩展导出;与 `vault_session_export` 输出的格式一致) |
@@ -105,10 +161,25 @@ dsh-vault 是一个面向 DeepSeek Harness 的安全加密插件:把你在使
105
161
  | `vault_session_export` | 将会话导出为 `Cookie` 请求头、Netscape cookie-jar 文件(curl `-b`)、原始 JSON(Playwright `addCookies` 格式)或可直接运行的 Playwright 片段 |
106
162
  | `vault_session_close` | 关闭已打开的浏览器登录会话(已收集的 cookie 仍保留在保险库中) |
107
163
  | `vault_session_prune` | 移除已保存会话中的过期 cookie(无过期的会话 cookie 保留);`preview: true` 只报告不修改 |
108
- | `vault_copy` | 复制条目(含密钥)到另一个命名保险库 |
109
- | `vault_templates` | 内建 + 用户自定义模板(save/list/remove,KeePassXC 风格);内建模板新增 Wi-Fi、服务器、数据库、身份、银行账户、银行卡(借鉴 1Password) | 内建 + 用户自定义模板(save/list/remove,KeePassXC 风格) |
110
164
 
111
- **典型开发场景**:存一条 SSH 凭据(`kind: ssh` + host/port/username/password 或 privateKey),开发时让模型 `vault_search` 找主机、`vault_get` 取连接信息;存 API 网关的 `api-key`/`oauth` 条目管理 access/refresh token 轮换。
165
+ ### 备份与保险库文件(完整档,或自定义 → 备份与文件) — 14
166
+
167
+ 备份、切换保险库、换密钥、恢复码与系统搜索。
168
+
169
+ | 工具 | 说明 |
170
+ |---|---|
171
+ | `vault_recovery_code` / `vault_verify_recovery` / `vault_recovery_status` | 一次性保险库恢复码(1Password/Bitwarden 风格):32 位代码仅显示一次,只保存其 SHA-256 哈希;可验证代码持有;查询是否已设置 |
172
+ | `vault_rekey` | 原地升级 scrypt KDF 参数并重加密 |
173
+ | `vault_switch` | 为当前会话切换活动保险库 |
174
+ | `vault_backup` / `vault_backup_now` | 时间戳加密备份,文件名 `<库名>-backups-YYYY-MM-DD_HH-MM-SS-<hex>.json`(库名+日期一目了然);自动保留最近 N 份 |
175
+ | `vault_restore_backup` | 从备份还原:`mode: "merge"`(默认)把备份条目复制进当前库,出现在条目列表;`mode: "replace"` 整体覆盖(先写安全快照) |
176
+ | `vault_vault_rename` / `vault_vault_delete` | 重命名命名库(文件移动,当前会话跟随)或永久删除(default 库受保护) |
177
+ | `vault_search_system` | 在 Chrome / 钥匙串中搜索站点与用户名——绝不暴露密码 |
178
+ | `vault_backup_status` | 报告距上次备份已过去多少天(1Password 式备份提醒) |
179
+ | `vault_search_history` | 搜索时包含已软删除(回收站)的条目,并标注其删除状态 |
180
+ | `vault_backups` | 列出可用的加密备份文件(最新在前)及其绝对路径与时间戳 |
181
+
182
+ **典型用法**:把 SSH 凭据存成 `kind: ssh`(host/port/username/password 或 privateKey),让模型先 `vault_search` 找到主机、再 `vault_get` 取连接信息;`api-key`/`oauth` 条目用于 API 网关的 access/refresh token 轮换。
112
183
 
113
184
  ## 安装
114
185
 
@@ -470,15 +541,25 @@ git clone git@github.com:Ox0400/dsh-vault.git
470
541
  cd dsh-vault
471
542
  pnpm install # 安装 devDependencies(typescript/tsdown/vitest 等)
472
543
  pnpm build # 构建 host 侧 lib/*.js 与浏览器 bundle lib/client.js
473
- pnpm test # 运行 496 项 vitest 测试
544
+ pnpm test # 运行 506 项 vitest 测试
474
545
  ```
475
546
 
476
547
  > 测试需要 harness 的 `dsh-llm`/`dsh-system-prompt` 等 peer 包,在 harness monorepo 内开发时由 workspace 链接提供。
477
548
 
549
+ 凭据列表里的品牌图标是**内联进浏览器包**的 68 条 SVG 路径 —— 没有运行时依赖,也不联网。它们是生成的,而且生成器就在仓库里:
550
+
551
+ ```sh
552
+ npm i --no-save simple-icons@16 # 15 MB,仅开发用;永远不会成为本包的依赖
553
+ pnpm gen:icons # 重新生成 src/client/site-icons.ts
554
+ pnpm gen:icons -- --check # 与上游不一致时退出 1
555
+ ```
556
+
557
+ 生成器只重写图标表;`gist.github.com`、`console.cloud.google.com` 这类**主机→品牌映射是人工整理的判断**,会原样保留。simple-icons 后来下架的品牌(`amazonaws`、`slack`、`linkedin` 等)会被保留并列出,而不是被静默丢掉。
558
+
478
559
  常用命令:
479
560
 
480
561
  ```sh
481
- # 单元 + 集成测试(vitest,496 项)
562
+ # 单元 + 集成测试(vitest,506 项)
482
563
  pnpm test # 或 npx vitest run
483
564
 
484
565
  # 类型检查
@@ -491,7 +572,7 @@ pnpm build # = build:host (tsc) + build:client (tsdown)
491
572
  npm pack
492
573
  ```
493
574
 
494
- 仓库内所有测试通过:496/496(crypto/TOTP/密码生成/store CRUD/网关/集成)。
575
+ 仓库内所有测试通过:506/506(crypto/TOTP/密码生成/store CRUD/网关/集成)。
495
576
 
496
577
  浏览器侧检查跑在真实 `dsh web` 上(不属于 vitest),且**一律拒绝在 default 库上运行**:
497
578
 
@@ -547,10 +628,25 @@ npm publish --access public # 发布 npm → dsh plugin add dsh-vault
547
628
 
548
629
  ## 安全边界与已知限制
549
630
 
550
- - 主密码强度决定保险库强度;建议 ≥ 16 字符高熵。
551
- - scrypt 成本参数(N=32768, r=8, p=1)已持久化在文档中,可随版本提升,旧文档仍可解密。
552
- - 明文凭据仅存在于进程内存与 `vault_get` 显式读取期间;`vault_search`/`vault_update` 的输出均不含密码、密钥与令牌。`vault_get` 返回的秘密会进入该次工具调用结果(模型上下文),调用方应避免在对话中复述。
553
- - 本插件面向单机/个人部署;团队共享保险库不在范围内。
631
+ ### 它保护什么
632
+
633
+ - **离开这台机器的保险库文件** —— 备份、同步盘、被拿走的硬盘。条目用 AES-256-GCM 加密,密钥由主密码经 scrypt 派生(N=32768, r=8, p=1,参数持久化在文档里,以后可提升;旧文档仍可解密)。
634
+ - **同一台机器上的其他用户** —— 保险库文件与 CLI 写出的文件都是 `0600`。
635
+ - **秘密意外进入模型上下文** —— `vault_search` / `vault_update` 从不返回密码、密钥或令牌;CLI 的存在就是为了让脚本取密钥时不必经过一次对话。
636
+ - **把密码写进配置文件** —— 前提是你用 `masterPasswordEnv` 而不是 `masterPassword`(见上方警告)。
637
+
638
+ ### 它不保护什么
639
+
640
+ - **同一个宿主进程里的其他插件。** dsh-vault 自己就是个插件:它与 harness 同进程运行,解密后的条目就在那个进程的内存里。`readonly` / `ask` / `auto` 约束的是**模型的工具调用**,不是插件之间的隔离。harness 对自己的凭据存储也是同样的说法:agent 的工具进程以你的 OS 用户身份运行,因此"无法把秘密与 agent 隔离"([`@deepseek-ai/dsh-credentials-local`](https://github.com/deepseek-ai/deepseek-harness/tree/main/packages/credentials/credentials-local))。只有把插件放到独立进程运行才能改变这一点,而这不是某个插件能自己做到的。
641
+ - **被攻陷的机器或账号** —— 键盘记录器、挂在 harness 进程上的调试器,或任何以你的身份运行的东西。
642
+ - **你自己敲进文件、截图或 shell 历史里的主密码。** 所以才要 `masterPasswordEnv`。
643
+ - **模型拿到值之后做什么。** `vault_get` 会把值放进该次工具调用的结果,也就是模型上下文;`vault_search`/`vault_update` 则从不暴露。
644
+
645
+ ### 减少暴露面
646
+
647
+ `lockTimeoutSeconds` 会在空闲后自动锁库,`vault_lock` 可以随时手动锁;两者都会清空内存中的密钥。把主密钥交给操作系统钥匙串(macOS Keychain / Windows Credential Manager / libsecret)能让明文密码**不再出现在配置与环境文件里** —— 也就是"磁盘被复制后仍然存在"的那部分暴露 —— 但它**不会**造出进程内边界:以你的身份运行的插件同样可以向钥匙串索取同一个条目。DSH 项目目前把"OS 钥匙串凭据提供方"列为待做事项。
648
+
649
+ 已知限制:本插件面向单机/个人部署;团队共享保险库不在范围内。
554
650
 
555
651
  ## 已收录于
556
652
 
package/README.md CHANGED
@@ -27,7 +27,7 @@ Each record has a `title`, an optional `kind`, and any combination of fields:
27
27
 
28
28
  | Field | Description |
29
29
  |---|---|
30
- | `kind` | `login` (default) / `ssh` / `api-key` / `secret` / `oauth` / `custom` |
30
+ | `kind` | `login` (default) / `ssh` / `api-key` / `secret` / `oauth` / `cookie` / `card` / `custom` |
31
31
  | `username` / `email` / `phone` | Account identity |
32
32
  | `password` | The password |
33
33
  | `host` / `port` | SSH host and port (e.g. `db.internal` / `2222`) |
@@ -37,35 +37,46 @@ Each record has a `title`, an optional `kind`, and any combination of fields:
37
37
  | `accessToken` / `refreshToken` / `expiresAt` | OAuth token pair and expiry (epoch millis) |
38
38
  | `otpSecret` | TOTP secret (bare Base32 or otpauth:// URI) |
39
39
  | `url` / `notes` / `tags` | Metadata |
40
+
41
+ Two kinds carry their own shape: a `cookie` entry stores a captured browser session, and a `card` entry stores `cardNumber` / `cardExpiry` (MM/YY) / `cardCvv` / `cardHolder` — search summaries expose only the expiry and holder, never the number or CVV, and the Bitwarden JSON export maps it to a `card` item (type 3, brand inferred).
40
42
  | `fields` | Arbitrary key/value pairs (e.g. `{"region": "us-east-1"}`), searchable |
41
43
 
42
44
  ## Tools
43
45
 
46
+ 113 tools in five groups. **Basic** is what a default install registers; the rest are switched on through [Tool profiles](#tool-profiles) (Settings → Credentials → Permissions → Model tools).
47
+
48
+ ### Basic (registered by default) — 11
49
+
50
+ Eleven tools. Everything below is opt-in.
51
+
44
52
  | Tool | Purpose |
45
53
  |---|---|
46
- | `vault_add` | Add an entry (any combination of fields; empty strings/arrays are ignored) |
47
- | `vault_get` | Read a full entry by id (including all secrets) |
54
+ | `vault_list` | List available vaults in the vault directory (one .json file per vault, excluding access/meta/export files) |
48
55
  | `vault_search` | Search titles/categories/usernames/emails/phones/hosts/ports/URLs/notes/tags/custom fields (incl. numeric/boolean/nested values; whitespace-separated terms OR-match); optional `createdAfter`/`createdBefore` epoch-millis filters; returns secret-free summaries; `limit` must be an integer 1–100 |
56
+ | `vault_get` | Read a full entry by id (including all secrets) |
57
+ | `vault_add` | Add an entry (any combination of fields; empty strings/arrays are ignored) |
49
58
  | `vault_update` | Update fields by id (unprovided fields kept; empty string clears a field; `title` is renamable; `rotationDays: 0` clears rotation = never rotate) |
50
- | `vault_compare` | Compare two entries field by field (`onlyA`/`onlyB`/`differ`/`equal`) — field names only, never secret values |
51
- | `vault_rename` | Rename an entry in one call (shortcut for `vault_update`) |
52
59
  | `vault_delete` | Soft-delete an entry (moves it to the trash, still encrypted on disk) |
53
- | `vault_restore` / `vault_purge` / `vault_restore_recent` | Bring a trashed entry back / purge it / undo the last delete |
54
- | `vault_lock` / `vault_unlock` | Explicitly lock the vault (wipe the in-memory key) / re-unlock it |
60
+ | `vault_fill` | Find the entry matching a host/URL/username/title and return its credentials |
61
+ | `vault_clipboard` | Fetch one entry secret field for direct copy (username/password/apiKey/...) |
55
62
  | `vault_totp` | Generate the current 6-digit code for a stored otpSecret (or a bare Base32 / otpauth URI) |
56
63
  | `vault_generate_password` | Generate a strong random password (length/classes/grouping) **or a memorable passphrase** (`passphrase: true`, EFF-style word list, `words`/`separator`/`wordDigits`) |
57
64
  | `vault_strength` | Zero-dependency password strength estimate (score 0–100, weak/fair/strong/very strong) |
65
+
66
+ ### Management (Standard and up) — 53
67
+
68
+ Favourites, tags, history, health, templates, attachments, card and 2FA detail.
69
+
70
+ | Tool | Purpose |
71
+ |---|---|
72
+ | `vault_compare` | Compare two entries field by field (`onlyA`/`onlyB`/`differ`/`equal`) — field names only, never secret values |
73
+ | `vault_rename` | Rename an entry in one call (shortcut for `vault_update`) |
74
+ | `vault_restore` / `vault_purge` / `vault_restore_recent` | Bring a trashed entry back / purge it / undo the last delete |
75
+ | `vault_lock` / `vault_unlock` | Explicitly lock the vault (wipe the in-memory key) / re-unlock it |
58
76
  | `vault_password_history` | List an entry's previous passwords (1Password/Bitwarden-style, newest first, capped at 10; current password excluded) |
59
- | `kind: card` | Bank/credit-card entries: `cardNumber`/`cardExpiry` (MM/YY)/`cardCvv`/`cardHolder`; search summaries expose expiry + holder only (never the number or CVV); Bitwarden JSON export maps to a `card` item (type 3, brand inferred) |
60
77
  | `vault_password_rollback` | Restore an entry password to a stored history entry (current password is archived first, so it is reversible) |
61
- | `vault_recovery_code` / `vault_verify_recovery` / `vault_recovery_status` | One-time vault recovery code (1Password/Bitwarden-style): 32-char code shown once, only its SHA-256 hash is stored; verify possession of the code; check whether one is set |
62
- | `vault_rekey` | Upgrade the vault to fresh scrypt KDF parameters in place |
63
- | `vault_backup` | Timestamped encrypted backup with retention; optional `note` |
64
- | `vault_import_csv` | Bulk-import credentials from a CSV file (custom columns become fields; `overwrite: true` merges fields into existing entries instead of duplicating) |
65
- | `vault_bulk_delete` | Soft-delete entries matching a query/kind/tag or explicit ids; `confirm: true` required (dry-run by default); trashed entries are restorable |
66
78
  | `vault_apply_tags` | Bulk add/remove/replace tags on every entry matching a query (dry-run supported, no secrets) |
67
79
  | `vault_totp_uri` | Build an otpauth:// provisioning URI for a stored or bare TOTP secret |
68
- | `vault_switch` / `vault_list` | Switch the active vault by name / list available vaults |
69
80
  | `vault_rotation` | Report expired / due-for-rotation / expiring-soon credentials; `soonWindowDays` (1-90, default 7) tunes the soon horizon (no secrets) |
70
81
  | `vault_health` | Vault health scan: weak/reused passwords, missing 2FA, insecure http:// sites, and an overall security score (0–100) |
71
82
  | `vault_watchtower` | Watchtower-style per-entry risk analysis (1Password/Bitwarden-inspired): flags short/weak passwords, keyboard sequences, embedded years, common passwords, reuse, http:// sites, missing 2FA, expiry — with a 0–100 score and good/warn/poor verdict (no secrets); entry rows show ⚠ badges |
@@ -79,13 +90,42 @@ Each record has a `title`, an optional `kind`, and any combination of fields:
79
90
  | `vault_verify` | Verify one entry or audit every entry (`all: true`) for per-kind completeness, port/expiry sanity (no secrets) |
80
91
  | `vault_duplicates` | Find duplicate groups: `mode` = `both` (default) / `title` / `content` (no secrets) |
81
92
  | `vault_report` | Printable inventory with expiry/rotation columns and a stats footer (no secrets) |
82
- | `vault_export` / `vault_import` | Portable encrypted backup/migration of the whole vault (separate export password) |
83
- | `vault_backup` / `vault_backup_now` | Timestamped encrypted backup named `<vault>-backups-YYYY-MM-DD_HH-MM-SS-<hex>.json` (owning vault + date visible); retention pruning keeps the newest N (`maxBackups`, default 10) |
84
- | `vault_restore_backup` | Restore from a backup: `mode: "merge"` (default) copies the backup entries INTO the current vault so they appear in the entries list; `mode: "replace"` overwrites the whole vault with a safety snapshot first |
85
- | `vault_vault_rename` / `vault_vault_delete` | Rename a named vault (file moves, active session follows) or permanently delete one (default vault protected) |
86
93
  | `vault_match_url` | Find login entries matching a URL (Bitwarden/1Password-style: exact host, subdomain, parent domain, path-prefix; www./port normalization) with a 0–100 score — never returns the password |
87
- | `vault_fill` | Find the entry matching a host/URL/username/title and return its credentials |
88
94
  | `vault_env` | Render env-flagged entries (tags contain `env`) as `KEY=VALUE` lines — see [Environment export](#environment-export) |
95
+ | `vault_copy` | Copy an entry (secrets included) into another named vault |
96
+ | `vault_templates` | Built-in + user-defined templates (save/list/remove), KeePassXC-style; built-ins now include Wi-Fi, Server, Database, Identity, Bank account, Card (1Password-inspired) |
97
+ | `vault_notes` | Append to or replace the free-form notes of an entry (a convenient shortcut for vault_update) |
98
+ | `vault_changes` | List vault activity within a time window (default 24h): entries created, updated, or soft-deleted, newest first |
99
+ | `vault_find` | Fuzzy-find entries: matching ignores case, punctuation and whitespace, so `gh` reaches `GitHub` |
100
+ | `vault_mask` | Redact likely credentials in arbitrary text (API keys, tokens, passwords, private keys) so it can be logged or quoted safely |
101
+ | `vault_history` | Show recent activity on the vault within this process, newest first: mutations (add/update/delete/restore/purge/merge/rollback) plus reads (read, totp), searches and vault switches. Records only the action, entry title and timestamp — never passwords, keys, usernames or other secret values |
102
+ | `vault_recent` | List the most recently created or updated entries (newest first), as secret-free summaries |
103
+ | `vault_pin` | Pin (favorite) an entry so it ranks first in search and list |
104
+ | `vault_unpin` | Unpin an entry (remove its favorite flag) |
105
+ | `vault_tags` | List every tag used across entries with the number of entries per tag |
106
+ | `vault_generate_username` | Generate a random username or an anonymous email suggestion |
107
+ | `vault_rotate_password` | Generate a new strong password, store it on the entry, and return the new value for the caller to hand to the target service |
108
+ | `vault_touch` | Mark an entry as recently used (update its updatedAt without changing content) |
109
+ | `vault_note_secret` | Store a single secret under a generated title (a one-off note without naming it) |
110
+ | `vault_search_advanced` | Search with multiple optional criteria: title substring, username/email substring, kind, tag, created-after/before (epoch millis), and favorite-only |
111
+ | `vault_count` | Return the number of active entries (optionally filtered by kind and/or tag) |
112
+ | `vault_set_icon` | Set the UI icon (emoji) and/or accent color on an entry |
113
+ | `vault_describe` | Describe an entry in plain language (kind, identity, host/url, tags, expiry) without revealing secrets |
114
+ | `vault_last_modified` | List entries most recently modified (updatedAt), newest first |
115
+ | `vault_has` | Quickly check whether the vault contains a credential matching a title/username/host (substring, or exact title when exact is set) |
116
+ | `vault_autofill_check` | Check whether the vault has a credential usable for a URL/host: returns the best matching entry (username/email only, never the secret) or a not-found verdict |
117
+ | `vault_undelete_all` | Restore ALL soft-deleted (trashed) entries back to the active set |
118
+ | `vault_get_many` | Read multiple entries by id, returning only the requested fields for each |
119
+
120
+ ### Import & export (Full, or Custom → Import-export) — 27
121
+
122
+ Migrating in and out of other password managers, bulk operations, and env/CSV/1Password/Bitwarden/KeePass/pass interop.
123
+
124
+ | Tool | Purpose |
125
+ |---|---|
126
+ | `vault_import_csv` | Bulk-import credentials from a CSV file (custom columns become fields; `overwrite: true` merges fields into existing entries instead of duplicating) |
127
+ | `vault_bulk_delete` | Soft-delete entries matching a query/kind/tag or explicit ids; `confirm: true` required (dry-run by default); trashed entries are restorable |
128
+ | `vault_export` / `vault_import` | Portable encrypted backup/migration of the whole vault (separate export password) |
89
129
  | `vault_export_bitwarden` / `vault_import_bitwarden` | Bitwarden/Vaultwarden JSON interop (full field mapping, overwrite support) |
90
130
  | `vault_import_bitwarden_encrypted` | Decrypt a Bitwarden password-protected JSON export (PBKDF2/Argon2id + HKDF → AES-256-CBC + HMAC) and import it; pass the export passphrase |
91
131
  | `vault_import_manager_csv` | Password-manager CSV auto-detected by header: Bitwarden (`login_uri`/`login_username`/…), 1Password 8, Dashlane, NordPass, Keeper, LastPass (`fav`/`grouping`/`extra`); dryRun preview |
@@ -96,7 +136,23 @@ Each record has a `title`, an optional `kind`, and any combination of fields:
96
136
  | `vault_import_keepass_xml` | KeePass 2.x XML export (plaintext or `********` masked values) |
97
137
  | `vault_import_chrome` / `vault_import_keychain` | Import passwords from Chrome's Login Data (macOS keychain / Linux keyring or `peanuts` / Windows DPAPI) or the macOS Keychain (internet passwords `inet` by default — the ones that actually back website logins — or generic `genp` via `classes`; session cache + preview, no prompt spam); every file import supports `dryRun` preview |
98
138
  | `vault_import_firefox` | Firefox profile import (logins.json + key4.db, NSS 3DES / PBES2-AES, primary-password aware) |
99
- | `vault_search_system` | Search Chrome / Keychain for sites & usernames — never exposes passwords |
139
+ | `vault_export_totp` | List every entry that has a TOTP secret, with its title and issuer label |
140
+ | `vault_bulk_export` | Export ALL entries (including secrets) as a JSON file for audit or migration |
141
+ | `vault_export_browser` | Export login entries in the browser password-manager CSV format (name,url,username,password) for importing into Chrome/Firefox/Edge |
142
+ | `vault_migrate_keepass` | Export entries in KeePass 2.x import CSV format (Group,Title,Username,Password,URL,Notes) for migrating into KeePass |
143
+ | `vault_export_keepass_xml` | Export entries as a KeePassXC-compatible XML document (KeePass 2.x schema) |
144
+ | `vault_import_browser` | Import a browser password-manager CSV (name,url,username,password — Chrome/Firefox/ Edge export format) |
145
+ | `vault_export_wallet` | Export entries as a directory tree of files compatible with pass (the standard Unix password manager): one file per entry containing the password, with metadata in comments |
146
+ | `vault_import_wallet` | Import entries from a pass directory tree: each .gpg file (or plaintext file) becomes an entry titled by its filename; the first line is the password, remaining lines are parsed as login:/email:/url: metadata. Returns added/skipped |
147
+ | `vault_export_env` | Write env-flagged entries (tags contain "env") to a .env file at the given path as KEY=VALUE lines (values shell-quoted) |
148
+ | `vault_export_csv` | Export vault entries to a CSV file (the same shape vault_import_csv accepts), optionally filtered by kind |
149
+
150
+ ### Browser sessions (Full, or Custom → Browser sessions) — 8
151
+
152
+ Capturing and replaying cookie sessions; needs the optional `playwright-core`.
153
+
154
+ | Tool | Purpose |
155
+ |---|---|
100
156
  | `vault_session_open` | Open a real headed browser window at a URL so the user can log in manually (password, 2FA, captcha) — the portable way to capture login state for sites that block embedding — requires the optional `playwright-core` |
101
157
  | `vault_session_collect` | Collect every cookie of an open browser session (incl. HttpOnly) and save it as a `cookie` entry |
102
158
  | `vault_session_import` | Save session cookies from pasted JSON (devtools export shape) or a raw `Cookie` header string — the no-browser alternative |
@@ -105,8 +161,23 @@ Each record has a `title`, an optional `kind`, and any combination of fields:
105
161
  | `vault_session_export` | Export a saved session as a `Cookie` header value, a Netscape cookie-jar file (curl `-b`), raw JSON (Playwright `addCookies` shape), or a ready-to-run Playwright snippet |
106
162
  | `vault_session_close` | Close an open browser login session (collected cookies stay in the vault) |
107
163
  | `vault_session_prune` | Remove expired cookies from a saved session (session cookies are kept); `preview: true` reports without writing |
108
- | `vault_copy` | Copy an entry (secrets included) into another named vault |
109
- | `vault_templates` | Built-in + user-defined templates (save/list/remove), KeePassXC-style; built-ins now include Wi-Fi, Server, Database, Identity, Bank account, Card (1Password-inspired) | Built-in + user-defined templates (save/list/remove), KeePassXC-style |
164
+
165
+ ### Backups & vault files (Full, or Custom → Backups & files) — 14
166
+
167
+ Backups, vault switching, rekeying, recovery codes and system search.
168
+
169
+ | Tool | Purpose |
170
+ |---|---|
171
+ | `vault_recovery_code` / `vault_verify_recovery` / `vault_recovery_status` | One-time vault recovery code (1Password/Bitwarden-style): 32-char code shown once, only its SHA-256 hash is stored; verify possession of the code; check whether one is set |
172
+ | `vault_rekey` | Upgrade the vault to fresh scrypt KDF parameters in place |
173
+ | `vault_switch` | Switch the active vault for this session |
174
+ | `vault_backup` / `vault_backup_now` | Timestamped encrypted backup named `<vault>-backups-YYYY-MM-DD_HH-MM-SS-<hex>.json` (owning vault + date visible); retention pruning keeps the newest N (`maxBackups`, default 10) |
175
+ | `vault_restore_backup` | Restore from a backup: `mode: "merge"` (default) copies the backup entries INTO the current vault so they appear in the entries list; `mode: "replace"` overwrites the whole vault with a safety snapshot first |
176
+ | `vault_vault_rename` / `vault_vault_delete` | Rename a named vault (file moves, active session follows) or permanently delete one (default vault protected) |
177
+ | `vault_search_system` | Search Chrome / Keychain for sites & usernames — never exposes passwords |
178
+ | `vault_backup_status` | Report how many days have passed since the last backup file was written (1Password-style backup reminder; new-style `<vault>-backups-<date>.json` and legacy `vault-backup-<epoch>.json` names are both recognized). Returns daysSinceBackup and a suggestion |
179
+ | `vault_search_history` | Search including soft-deleted (trashed) entries, marked with their deleted state |
180
+ | `vault_backups` | List available encrypted `vault-backup-*.json` files (newest first) with their absolute paths and timestamps |
110
181
 
111
182
  **Typical workflows**: store an SSH credential (`kind: ssh` + host/port/username/password or privateKey) and have the model `vault_search` for the host then `vault_get` the connection details; keep `api-key`/`oauth` entries for API-gateway access/refresh token rotation.
112
183
 
@@ -539,21 +610,31 @@ git clone git@github.com:Ox0400/dsh-vault.git
539
610
  cd dsh-vault
540
611
  pnpm install # installs devDependencies (typescript/tsdown/vitest, …)
541
612
  pnpm build # builds host lib/*.js and the browser bundle lib/client.js
542
- pnpm test # runs the 496 vitest tests
613
+ pnpm test # runs the 506 vitest tests
543
614
  ```
544
615
 
545
616
  > Tests need harness peer packages such as `dsh-llm`/`dsh-system-prompt`; inside the harness monorepo these resolve via workspace links.
546
617
 
618
+ The brand marks in the credential list are 68 SVG paths inlined into the browser bundle — no runtime dependency and no network call. They are generated, and the generator is committed:
619
+
620
+ ```sh
621
+ npm i --no-save simple-icons@16 # 15 MB, dev-only: never a dependency of this package
622
+ pnpm gen:icons # refreshes src/client/site-icons.ts
623
+ pnpm gen:icons -- --check # exits 1 when the table is stale
624
+ ```
625
+
626
+ Only the glyph table is rewritten; the host→brand map (`gist.github.com`, `console.cloud.google.com`) is curated knowledge and is preserved. Brands that simple-icons has since removed (`amazonaws`, `slack`, `linkedin`, …) are kept and reported rather than dropped.
627
+
547
628
  Common commands:
548
629
 
549
630
  ```sh
550
- pnpm test # unit + integration tests (vitest, 496)
631
+ pnpm test # unit + integration tests (vitest, 506)
551
632
  pnpm typecheck # tsc -p tsconfig.json --noEmit
552
633
  pnpm build # = build:host (tsc) + build:client (tsdown)
553
634
  npm pack # optional: tarball for `dsh plugin add ./dsh-vault-0.1.1.tgz`
554
635
  ```
555
636
 
556
- All 496 tests pass (crypto / TOTP / password generation / store CRUD / gateway / integration).
637
+ All 506 tests pass (crypto / TOTP / password generation / store CRUD / gateway / integration).
557
638
 
558
639
  Browser checks run against a real `dsh web` instead of vitest, and every one of
559
640
  them refuses to operate on the default vault:
@@ -625,10 +706,25 @@ npm publish --access public # registry → dsh plugin add dsh-vault
625
706
 
626
707
  ## Security Boundaries & Known Limitations
627
708
 
628
- - Vault strength is bounded by master-password strength; use ≥ 16 characters of high entropy.
629
- - scrypt cost parameters (N=32768, r=8, p=1) are persisted in the document and can be raised in future versions; old documents remain decryptable.
630
- - Plaintext credentials exist only in process memory and during explicit `vault_get` reads; `vault_search`/`vault_update` outputs never contain passwords, keys, or tokens. Secrets returned by `vault_get` enter that tool call's result (model context) — callers should avoid repeating them in conversation.
631
- - This plugin targets single-machine / personal deployments; team-shared vaults are out of scope.
709
+ ### What this protects
710
+
711
+ - **A vault file that leaves the machine** — a backup, a synced folder, a stolen disk. Entries are AES-256-GCM encrypted under a key derived from the master password with scrypt (N=32768, r=8, p=1, persisted in the document and raisable later; old documents stay decryptable).
712
+ - **Other users on the same machine** — the vault and every file the CLI writes are `0600`.
713
+ - **Secrets reaching the model's context by accident** — `vault_search` / `vault_update` never return passwords, keys or tokens, and the CLI exists so a script can read a secret without it passing through a conversation.
714
+ - **A password embedded in config**, when you use `masterPasswordEnv` instead of `masterPassword` (see the warning above).
715
+
716
+ ### What this does not protect
717
+
718
+ - **Another plugin in the same host process.** dsh-vault is itself a plugin: it runs in-process with the harness and decrypted entries live in that process's memory. `readonly` / `ask` / `auto` constrain **the model's tool calls** — they do not isolate plugins from one another. The harness states the same limit for its own credential store: agent tool processes run as your OS user, so it "cannot isolate secrets from the agent" ([`@deepseek-ai/dsh-credentials-local`](https://github.com/deepseek-ai/deepseek-harness/tree/main/packages/credentials/credentials-local)). Only running plugins out-of-process would change this, and no plugin can enforce that by itself.
719
+ - **A compromised machine or user account** — a keylogger, a debugger attached to the harness process, or anything else running as you.
720
+ - **A master password you typed into a file, a screenshot or a shell history.** Hence `masterPasswordEnv`.
721
+ - **What the model does with a value you let it read.** `vault_get` returns it into that tool call's result, which is model context; `vault_search`/`vault_update` never expose one.
722
+
723
+ ### Reducing the exposure
724
+
725
+ `lockTimeoutSeconds` auto-locks an idle vault and `vault_lock` locks it on demand; both wipe the in-memory key. A master key held by the OS keychain (macOS Keychain / Windows Credential Manager / libsecret) would take the plaintext password out of config and environment files — the exposure that survives a disk copy — but it would **not** create an in-process boundary, because a plugin running as you can ask the keychain for the same item. The DSH project lists an OS-keychain credentials provider as deferred work.
726
+
727
+ Known limitation: this plugin targets single-machine / personal deployments; team-shared vaults are out of scope.
632
728
 
633
729
  ## Listed in
634
730