dsh-daily-approval-guard
v0.1.0
Published
Unified high-risk operation approval gate and sensitive-data redaction for the DeepSeek Harness (developer preview)
Readme
approval-guard
dsh(DeepSeek Harness)统一高风险操作审批门 + 敏感信息脱敏插件。
状态:developer preview。已通过
tsc --noEmit类型检查(对齐@deepseek-ai/[email protected]的事件签名)与全部纯函数单测;尚未在真实 dsh 运行时中验证,手动验证步骤见下文。
功能
风险四级审批门,挂在
tools/pre-executewaterfall 上:| 级别 | 含义 | 默认行为 | | --- | --- | --- | | L0 | 本地只读 / 公开查询(read、glob、grep、web_search…) | 自动 allow | | L1 | 写用户指定目录 / 建草稿(write、todo_write、create_goal…) | 首次 ask;同会话同工具记住选择 | | L2 | 修改文件 / 发消息 / 执行命令(edit、bash、send_message…) | 每次 ask | | L3 | 删除 / 付款 / 发布 / 高风险命令 | 默认 deny(可配置降级为 ask) |
allow 时调用
next()委托下游策略(plan-mode、sandbox 等仍可否决);deny/ask 短路。工具风险分级表:内置映射基于 dsh master 源码核对的第一方工具名(
packages/fs、shell、web、jobs、todo、interaction、terminal、subagent、skill、lsp、session-query、goal下的 tool-* 包)。config.overrides可覆盖/追加;未知名工具(如 MCP 工具)落到defaultLevel(默认 L2,每次 ask)。L3 升级规则:对命令载荷类工具(bash / pwsh / run_code / terminal_send)内置高危命令模式(
rm -rf /、磁盘抹除、关机等)直接升为 L3;extraDenyPatterns可对任意工具的序列化参数强制 L3。这些规则先于overrides生效,不会被误配降级。路径/域名白名单:
allowedPaths(前缀比较,Windows 盘符路径大小写不敏感)与allowedDomains(后缀匹配,example.com覆盖api.example.com,不会误放notexample.com)。L1/L2 调用声明的路径/URL 全部命中白名单时降为 L0。审批审计:每次决定(工具名、脱敏后的参数摘要、风险级、决定、理由、时间)以
approval-guard/decision自定义事件 append 到会话日志;拿不到 session 的调用(如无 agent 的派发)退化为写插件自有 JSONL 文件(auditLog.filePath,默认approval-guard-audit.jsonl)。敏感信息脱敏:内置 API key / AWS AKIA / GitHub ghp_·gho_·github_pat_ / PEM 私钥头 /
.env风格KEY=value/ Bearer token /"apiKey": "…"键值对模式。用于两处:(a) 审计参数摘要(先脱敏后截断);(b)tools/post-execute支持替换结果投影(PostToolDecision { kind: 'accept', content },已核对签名),插件据此对进入会话的工具结果文本做脱敏。注意:post-execute 只能替换 content 投影,工具的规范 value 不变(见下方"已知限制")。
配置
- id: approval-guard
name: dsh-daily-approval-guard
config:
enabled: true
defaultLevel: 2 # 未知工具的风险级(0-3)
overrides: # 覆盖/追加工具分级
web_fetch: 2
my_mcp_tool: 3
allowedPaths: # 命中前缀的写操作降为 L0
- D:/code/scratch
allowedDomains: # 命中后缀的请求降为 L0
- example.com
sessionMemory: true # L1 同会话同工具记住选择
l3AsAsk: false # true 时 L3 由 deny 降级为 ask
extraDenyPatterns: [] # 命中即 L3 的额外正则(作用于序列化参数)
redaction:
extraPatterns: [] # 额外脱敏正则
redactResults: true # 是否脱敏工具结果文本
auditLog:
enabled: true
filePath: approval-guard-audit.jsonl
maxArgsLength: 200所有叶子字段都有默认值,空配置即可启用。
权限透明
- 读写位置:仅在无 agent session 可达时,向
auditLog.filePath(默认进程工作目录下的approval-guard-audit.jsonl)追加审计行;此外不读写任何文件。 - 网络域名:无。本插件不发起任何网络请求。
- 凭证:不持有、不读取任何凭证;只对流经参数/结果中形似凭证的文本做脱敏。
- 确认点:L1(首次)/ L2(每次)/ L3(仅当
l3AsAsk: true)的工具调用会返回ask,由 dsh 的 approval 服务向用户确认。 - 日志内容:会话事件
approval-guard/decision与兜底 JSONL 文件记录工具名、风险级、决定、理由、时间戳和脱敏且截断的参数摘要;绝不记录原始参数。
已知限制
- post-execute 的 content 替换是呈现层策略:工具的程序化 value(供复合工具/代码模式使用)不会被改写。dsh 官方文档明确 content 替换"是 presentation policy, not confidentiality policy";若某结果必须对模型彻底隐藏,正确做法是 pre-execute 阶段 deny。
- L1"记住选择"的语义是:某次 ask 被用户放行且工具执行成功后才记住;被拒绝的调用不会产生记忆。
- 脱敏基于正则模式,不能保证覆盖所有秘密形态;可用
redaction.extraPatterns补充。
手动验证
CI 只覆盖类型检查与纯函数单测。接入真实 dsh 后请按以下步骤验证:
- 在 dsh 配置中启用
approval-guard,启动日志应出现approval-guard: loaded。 - 让 agent 执行一次
read(L0)→ 应直接执行,会话日志出现一条approval-guard/decision(decision=allow)。 - 让 agent 执行一次
write(L1)→ 应弹出确认;放行并成功后,第二次同类write不再询问。 - 让 agent 执行一次
edit或bash(L2)→ 每次都应弹出确认。 - 让 agent 执行
bash且命令为rm -rf /→ 应被直接拒绝(decision=deny),无需确认弹窗。 - 在
allowedPaths中配置一个目录后让 agent 写入其中 → 应降为 allow。 - 让工具返回包含
AKIA…或ghp_…的文本 → 进入会话的结果应已替换为[REDACTED:…]。
许可
MIT
