← 返回列表
未验证
拦截敏感文件读写,掩码泄漏密钥并留审计日志
尚未跑自动兼容性验证,可查看页面内的依赖与入口分析。 · 最近上游提交 2026/8/17 · 已提供中文文档
dsh 安全插件:阻止代理读取/写入敏感文件(.env、凭据),在工具结果中屏蔽泄露的机密,审计日志,安全的 sg_* 检查工具
综合分
27.7
GitHub 分
27.7
用户评分
—
★ Stars
1
周下载量
—
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add JohnXu22786/secret-guard该插件未发布到 npm,走 GitHub 源安装(pnpm 若拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑)
数据截至 2026/9/16(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh-llm@deepseek-ai/dsh-tools用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动
README
English
secret-guard
面向 DeepSeek Harness(dsh)的安全插件:在 agent 的文件工具执行之前拦截对敏感文件的读写(.env、credentials、密钥文件等),防止 API 密钥等机密泄漏到对话上下文;并对工具结果做内容掩码兜底,即使有内容绕过了拦截也会被清洗。
- 零构建:纯 TypeScript 源码加载(dsh 用 Node 原生 strip-only 类型剥离加载 .ts,因此源码不得使用参数属性等 strip 不支持的语法——本仓库已遵守,并有 npm run smoke:strip 冒烟检查);自包含,运行时依赖仅 @deepseek-ai/dsh-tools(工具定义)与 schemastery(配置校验)。
- 拦截层:tools/pre-execute 瀑布事件(在工具体执行前短路)。
- 兜底层:tools/post-execute 瀑布事件(对结果内容做形状识别掩码)。
- 配套 sg_ 安全检查工具:只返回键名、行号、形状、布尔值与 HMAC 指纹,永不返回原始值。
- 审计日志:JSONL 追加式、按大小轮转;规则文件热加载(自动轮询 + 手动 sg_reload)。
目录结构
secret-guard/
package.json # dsh.bundle.patch 声明;main 指向源码
cordis.patch.yml # bundle 补丁层(插件行:id / name / config)
src/
index.ts # 插件入口:name / inject / Config / apply
config.ts # 配置 schema(schemastery)+ 校验与默认值
policy.ts # 规则引擎:路径归一化、glob 编译、默认规则表
gate.ts # tools/pre-execute 拦截监听器
scrub.ts # tools/post-execute 内容掩码监听器
inspect.ts # dotenv 解析、值形状分类、sg_ 安全工具
fingerprint.ts # HMAC-SHA256 封印密钥(seal key)与指纹
journal.ts # JSONL 审计日志 + 轮转
watch.ts # 规则文件热加载轮询器
tests/ # node:test + tsx,无需编译即可运行
README.md
LICENSE
在 DSH 中安装
dsh plugin --profile demo add github:JohnXu22786/secret-guard
安装后默认配置即生效。卸载:
dsh plugin --profile demo remove dsh-secret-guard
安装与接入(dsh 如何加载它)
插件遵循 dsh 的 Cordis 插件约定:一个导出 name / inject / Config / apply(ctx, config) 的 ESM 模块(入口 src/index.ts),由 cordis.patch.yml 作为 bundle 层插入插件树。注册的副作用(事件监听、工具注册、文件轮询)都在 apply 返回的清理函数与 Cordis 上下文中可逆卸载。
从本目录安装到 web profile(等效于 pnpm 链接 + bundle 层加载)
dsh plugin --profile web add .
或 headless profile
dsh plugin --profile headless add .
安装后默认配置即生效。检查插件树:
dsh --profile web --dump-config | grep -A 6 secret-guard
本地开发(不安装)
未安装到 profile 时,patch 行里的包名无法从 profile 目录解析,需要用绝对路径 overlay 指向源码入口。注意 Windows 上 Node 的 ESM 不认盘符路径(D:/… 会被当成协议),必须加 file:/// 前缀:
dev-overlay.yml
- insert:
- id: secret-guard-dev
name: 'file:///D:/path/to/secret-guard/src/index.ts'
config:
maskResults: true
dsh --profile headless --patch D:/path/to/secret-guard/dev-overlay.yml "请列出当前目录"
环境要求
- dsh ≥ 0.1.0-rc.6(@deepseek-ai/dsh-tools 类型即 0.1.0-rc.6 的接口面)
- Node.js ≥ 22.19(或 ≥ 24)
- peer 依赖:@deepseek-ai/cordis、@deepseek-ai/dsh-tools、@deepseek-ai/dsh-llm(仅类型)、schemastery(宿主 profile 需提供,dsh plugin add 会自动安装 peer)
插件接口一览
| 接口 | 说明 |
| --- | --- |
| 清单 | package.json 的 dsh.bundle.patch → cordis.patch.yml |
| 入口 | src/index.ts:name='secret-guard',inject=['tools'],apply(ctx, config) |
| 拦截事件 | 消费 tools/pre-execute(拒绝则返回 {kind:'deny', reason},短路瀑布) |
| 掩码事件 | 消费 tools/post-execute(返回替换内容后的 accept 决策) |
| 工具 | 注册 sg_keys / sg_scan / sg_fingerprint / sg_probe / sg_status / sg_reload |
| 配置 | 插件行的 config 字段(见下),由 schemastery Config 校验 |
配置
配置写在 cordis.patch.yml 的插件行 config 下,或通过 profile 的 cordis.patch.yml 补丁覆盖:
- insert:
- id: secret-guard
name: 'dsh-secret-guard'
config:
自定义规则(在默认规则之前求值,先匹配者胜)
rules:
- id: my-prod-creds
match: '/prod-secrets.yml'
effect: block # block | block-read | block-write | allow
reason: '生产凭据,禁止读写'
放行名单(在任何规则之前检查;同样支持 glob)
allow:
- 'tests/fixtures/.env'
- '/sandbox.env'
参与拦截的工具(参数含 file_path / path 的文件类工具;默认含 read_image)
gateTools: [read, write, edit, glob, grep, read_image]
grep 的 pattern 命中敏感关键词(env/credential/password…)时也拦截
guardSearchPatterns: true
结果内容掩码兜底
maskResults: true
封印密钥(HMAC):优先读环境变量,其次本地文件(自动创建,0600)
sealKey:
env: SECRET_GUARD_SEAL_KEY
path: .secret-guard/seal.key
审计日志
audit:
enabled: true
dir: .secret-guard/logs
maxBytes: 1048576 # 单文件超过即轮转
keep: 5 # 保留的轮转文件数
外部规则文件(JSON,可热加载):{ "rules": [...], "allow": [...] }
rulesFile: .secret-guard/rules.json
watchRules: true # 自动轮询热加载(约 400ms 周期)
相对路径(sealKey.path、audit.dir、rulesFile)均相对 dsh 的启动工作目录解析。
规则语法与默认规则表
规则 match 使用类似 .gitignore 的 glob:
- 包含 / 的模式锚定完整路径(/.aws/credentials 匹配任意深度);/ 前缀可匹配零层目录;
- 不含 / 的模式只匹配文件名(.env 匹配任意目录下的 .env);
- 跨目录段, 单段内任意,? 单字符;中间的 / 也匹配零层或多层目录(foo//bar 同样匹配 foo/bar,与 gitignore 一致);
- 匹配不区分大小写(对拦截型规则更安全)。
求值顺序:allow 放行名单 → 自定义 rules(按声明顺序)→ 内置默认规则(首条命中即止)。放行名单与规则中的 allow 效果一致,但放行名单永远最先检查。
匹配目标:规则与放行名单都作用于归一化路径——正斜杠、去掉盘符与前导 /、折叠 ..(a/../b → b)。因此模式请按相对形式书写(如 tests/fixtures/.env),不要带盘符(C:\…);按绝对路径写放行名单会静默失效。
内置默认规则(id 即日志中的 rule 字段):
| id | 匹配 | 效果 | 说明 |
| --- | --- | --- | --- |
| guard-vault | /.secret-guard/ | block | 插件自身存储(封印密钥、审计日志) |
| env-example ~ env-default | .env.example / .env.sample / .env.template / .env.dist / .env.default | allow | 安全的示例文件 |
| env-file | .env | block | 可能含真实机密 |
| env-variant | .env. | block | 环境特定机密文件 |
| env-suffixed | .env | block-read | 非标准命名(如 api.env) |
| aws-credentials | /.aws/credentials | block | |
| git-credentials | /.git-credentials | block | |
| netrc | /.netrc | block | |
| npmrc-auth | /.npmrc | block-read | 含 registry 令牌 |
| pypirc | /.pypirc | block-read | 含 registry 令牌 |
| credential-files | credential | block | 凭据存储 |
| ssh-rsa / ssh-ed25519 / ssh-ecdsa / ssh-dsa | id_rsa 等 | block-read | SSH 私钥(写入放行,支持密钥生成流程) |
| key-ext- | .pem .key .ppk .p12 .pfx .jks .keystore .kdbx | block-read | 私钥/密钥库材料 |
效果语义:block 读与写都拦;block-read 只拦读取类工具(read/read_image/glob/grep),写放行;block-write 反之;allow 全放行。
安全检查工具(sg_)
这些工具故意可以读取被拦截的文件——这正是它们的存在意义——但它们只返回元信息,任何输出路径都不会包含原始值。
| 工具 | 用途 | 返回 |
| --- | --- | --- |
| sg_keys | 列出 dotenv 文件的键 | 键名、行号、是否为空、值形状标签 |
| sg_scan | 值形状扫描 | 每个键的形状(empty/bool/numeric/jwt/url/hex/base64/opaque)与长度 |
| sg_fingerprint | 单个键的确定性指纹 | HMAC-SHA256 前 16 位十六进制(同一封印密钥下稳定) |
| sg_probe | 对单个键做布尔提问 | is-set / is-empty / starts-with / ends-with / contains / matches(正则,在独立 worker 线程中执行并限时,防病态正则卡死宿主) / equals(常数时间比较,不交换明文) 的布尔结果 |
| sg_status | 查看当前策略 | 规则数、放行名单、拦截工具、掩码/审计开关;check 参数可对任意路径做试分类 |
| sg_reload | 立即重读外部规则文件 | 重载结果(规则数/放行数/错误信息) |
用法示例(agent 视角):
sg_status { check: ".env" } # -> block (rule 'env-file')
sg_keys { file: ".env" } # 只列出键名
sg_probe { file: ".env", key: "DB_PASSWORD", op: "equals", value: "候选值" } # true/false
sg_fingerprint { file: ".env", key: "DB_PASSWORD" } # 9f2c… 稳定指纹
内容掩码兜底(scrub)
即使拦截被绕过(例如通过 bash 执行 cat .env、MCP 工具、未列入 gateTools 的工具),tools/post-execute 仍会对结果文本做形状识别,将疑似机密替换为 [redacted::],并追加一行摘要说明清洗数量。
能力边界(重要):掩码是文本形状匹配,不是安全边界。把内容变换后输出(cat .env | base64、rev、拆行拼接等)可以击穿全部形状规则;同理,符号链接、.. 等路径别名属于字符串分类的已知限制(见「安全注意事项」)。它只用于拦住"模型直接把机密原样读进上下文"这一最常见路径,不能替代拦截层。
识别形状(刻意保守,避免误伤哈希、UUID、普通长字符串):
- PEM 私钥块(-----BEGIN … PRIVATE KEY-----)
- JWT(eyJ… 三段式)
- Bearer 令牌(Bearer )
- 知名密钥前缀:ghp_/gho_/ghu_/ghs_/ghr_、sk-、AKIA…、xox[baprs]-
- 带明文的连接串(scheme://user:pass@host,要求存在 :密码@)
- key=value 赋值(键名含 password/passwd/secret/token/api_key/access_key/client_secret/private_key/auth_key,值 ≥ 12 字符且不是 /xxx/example 等文档占位)
刻意不掩码:裸 base64/十六进制长串(git 提交哈希、UUID 等误伤率高);仅当它们出现在上述上下文中才处理。
审计日志
所有拦截(block)、掩码(mask)、规则重载(reload)、错误(error)都会写入 audit.dir/events.jsonl(JSONL,追加式),超过 maxBytes 自动轮转为 events.1.jsonl、events.2.jsonl…,最多保留 keep 份。
日志契约:永不记录值——条目只含时间戳、事件类型、工具名、路径、规则 id、效果、形状计数、消息。日志路径本身也在默认规则 guard-vault 的保护范围内。
规则热加载
配置 rulesFile 指向一个 JSON 文件({ "rules": [...], "allow": [...] },结构与配置中的同名字段一致):
- watchRules: true 时每 400ms 轮询一次,文件变化(mtime/大小)后去抖 300ms 自动重载;
- 或随时调用 sg_reload 立即重载;
- 重载成功/失败都会写审计日志并在控制台提示;失败的加载不会破坏当前生效的规则(保留旧引擎)。
实现说明:轮询而非 fs.watch,是因为 Windows 上删除被监视目录会泄漏事件循环的退出资格(平台缺陷),且规则文件常被编辑器以重命名方式替换;轮询跨平台行为一致且无泄漏(定时器已 unref)。
安全注意事项
- 封印密钥(seal key)是 HMAC 指纹的根密钥:不要提交 .secret-guard/seal.key,建议加入 .gitignore;换机或重置后指纹会变化(属预期行为)。
- 默认把 sealKey.path / audit.dir 留在 .secret-guard/ 下(内置规则 guard-vault 会保护它们)。若改到别处,请自行配置等价拦截规则,否则 agent 可能读到密钥文件或审计日志。
- 默认规则刻意偏保守(宁可误拦),误拦时用 allow 放行名单精确放行,或 sg_status {check: …} 先验证分类结果。
- 本插件不迁移、不加密、不移动任何机密文件;它只阻止"把机密读进模型上下文"这一件事。
- 已知限制(设计取舍):路径分类是纯字符串匹配,不解析符号链接目标,.. 折叠只覆盖字符串层;通过 bash 等执行类工具读取敏感文件不受拦截层约束(掩码兜底尽力清洗输出)。sg_probe 的布尔提问是"值预言机"——理论上可用多轮 contains/equals 查询重构出值,它是为方便 agent 安全核对而设计,不应用于不可信上下文。
开发与测试
npm install # 仅 devDependencies(tsx / typescript / cordis 运行时 / schemastery)
npm test # node --import tsx --test tests/.test.ts(77 个用例,约 5 秒)+ strip-only 加载冒烟
npm run typecheck # tsc --noEmit
测试覆盖:规则引擎(归一化/glob/默认表/放行名单/自定义规则优先级)、dotenv 解析、指纹与封印密钥、掩码模式与误伤控制、拦截决策矩阵(含搜索工具与关键词守卫)、审计轮转、以及用真实 Cordis 上下文驱动瀑布事件的集成测试(含热加载端到端)。
许可
本项目以 MIT 许可协议发布。同作者(JohnXu22786)的其他插件
扫码进群