工具管线上的运行时安全网关:拦截出站白名单之外的主机调用,在 canonical value(而非仅渲染内容)层面脱敏结果中的凭据,每个决策写入 JSONL 审计日志;默认仅监控不拦截。
安装
# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)
dsh plugin --profile web add github:tancheng33/dsh-egress-guard
装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络,工具审批管不到它。GitHub 来源的插件还会在安装时执行构建脚本——pnpm 默认拦截,所以安装可能停在 ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED 或 ERR_PNPM_IGNORED_BUILDS;dsh 会打印出需要添加的确切键名,把它加进该 profile 的 pnpm-workspace.yaml 的 allowBuilds 下,重跑一次即可装上。放行构建本身就是一次信任判断:请只安装可信来源,并尽量锁定 commit(github:owner/repo#sha)。
README
English | 中文
给 DeepSeek Harness 工具调用加的运行时安全网关。
生态里已有的安全插件都是在 agent 跑起来之前静态扫描配置文件。这个插件挂在工具执行管线上,作用于调用本身:
| 规则 | 扩展点 | 作用 |
|---|---|---|
| 出站白名单 | tools/pre-execute |
调用里出现白名单之外的网络目的地时拒绝(或转审批)——curl 到某个 paste 站、git push 到陌生远端、fetch 到外传端点。 |
| 密钥脱敏 | tools/post-execute |
在模型、持久化会话日志、Code Mode 程序读到之前,把工具结果里的凭据改写掉。 |
| 审计日志 | 两条瀑布 | 每个决策都追加成一行 JSONL,包括 monitor 模式下"本来会拦"的那些。 |
不 fork、不改 loop:三个监听器挂在文档化的扩展点上,卸载时干净释放。
安装
dsh plugin --profile <名字> add dsh-egress-guard
bundle 默认是 mode: monitor,所以装上它不会弄坏你现有的配置:所有规则照常评估、照常写审计日志,但不拦截、不改写。先看一天日志,再去 profile 的 cordis.patch.yml 里打开强制:
- id: egress-guard
config:
mode: enforce
egress:
enabled: true
allowHosts: ['*.github.com', '*.npmjs.org', 'api.deepseek.com']
denyHosts: []
allowLoopback: true
onViolation: deny
redact:
enabled: true
builtins: true
extraPatterns: []
placeholder: '[redacted:{name}]'
audit:
enabled: true
path: ''
logAllowed: false
注意 patch 替换的是整个 config,不是深合并——你想保留的键都要重写一遍。
配置项
| 键 | 默认值 | 含义 |
|---|---|---|
mode |
monitor |
off 什么都不注册;monitor 只评估只记录;enforce 真拦真改。 |
egress.allowHosts |
schema 里为 [],bundle 里给了一份起步清单 |
放行的主机。*.example.com 同时覆盖主域名和所有子域名。留空表示只用黑名单。 |
egress.denyHosts |
[] |
始终拒绝,优先级高于 allowHosts 和 allowLoopback。 |
egress.allowLoopback |
true |
放行 localhost、127.0.0.0/8、::1、*.localhost。 |
egress.onViolation |
deny |
设成 ask 则交给 ctx.approval 审批——没挂审批服务时会降级为拒绝。 |
redact.builtins |
true |
内置:私钥、各家 API key、JWT、bearer 头、KEY=value 赋值。 |
redact.extraPatterns |
[] |
额外的正则(按 global 标志编译)。 |
redact.placeholder |
[redacted:{name}] |
{name} 会替换成命中的规则名。 |
audit.path |
$DSH_HOME/egress-guard.jsonl |
JSONL,一行一个决策。 |
audit.logAllowed |
false |
连"命中了主机但放行"的调用也记——这是用真实流量反推白名单的办法。 |
用真实流量反推白名单
# 1. 先用 monitor 模式装上,把 logAllowed 开成 true,正常干活一段时间
# 2. 看你的 agent 到底访问了哪些主机:
jq -r '.hosts[]?' ~/.dsh/egress-guard.jsonl | sort | uniq -c | sort -rn
# 3. 把合理的填进 allowHosts,再把 mode 切成 enforce
设计取舍
脱敏改的是 canonical value,不是渲染出来的 content。 注册表的契约里写得很明确:content 替换不是保密边界——Code Mode 的程序直接拿到的是 value。所以成功结果走 value 替换,content 由脱敏后的 value 重新渲染;失败结果没有 value(注册表禁止对失败结果替换 value),只能按 content 脱敏。
这个插件在 post-execute 瀑布里最后动手。 它先 next() 把下游跑完,再对最终决策实际携带的那份投影做脱敏,这样瀑布更深处的监听器没法把原文再塞回来。如果别的插件替换了 content 而底层 value 里还有密钥,本插件会替换 value——代价是丢掉那个插件的展示效果,但不会泄漏给程序化消费者。这个优先级是有意为之的。
拒绝时会明确告诉模型别绕路。 只回一句"denied"会诱导模型换个工具重试;这里的 reason 会点名主机,并要求它去问用户。
局限 —— 信任它之前请先读这段
这是护栏,不是隔离边界。它提高的是"手滑"和"轻度 prompt 注入"的成本,挡不住一个已经能在你机器上执行代码的对手。
- 检测是文本层面的:从参数字符串里扫 URL 和
user@host远端。运行期才拼出目的地的命令(curl "$ENDPOINT"、base64、字符串拼接、十进制形式的 IP)对这个网关完全隐形。真正的隔离是沙箱接缝该干的事(dsh-bash-sandbox、网络命名空间、代理),不是字符串匹配。 - 工具自己开 socket 就完全绕过,除非目的地出现在它的参数里。
- 脱敏基于模式匹配:不认识的凭据形状会漏,看起来像密钥的正常文本会被误改。自己的格式请加
extraPatterns;开强制之前先看审计日志里的误报。 - 不扫二进制内容:图片等非文本块原样透传。
- 审计日志在本地且未签名:任何能写你文件系统的东西都能改它。
兼容性
针对 @deepseek-ai/dsh-tools 0.1.5 / 0.1.6 的管线契约开发;逐版本声明写在 package.json 的 dsh.compatibility.dshReleases 里。
2026-09-22 验证,每条发布线都把整个 @deepseek-ai/dsh-* 家族钉到同一版本:
| DSH 版本 | 类型检查 | 构建 | 测试 |
|---|---|---|---|
0.1.5-rc.2(npm latest) |
通过 | 通过 | 61/61 |
0.1.6-alpha.1 |
通过 | 通过 | 61/61 |
0.1.6-alpha.2(npm alpha) |
通过 | 通过 | 61/61 |
在 0.1.5-rc.2 上还用打包 tarball 做了一次性 Profile 验证(DSH_HOME 指向临时目录,--from-default-profile headless):bundle 作为 egress-guard 行合入 profile 树,profile 带着它启动、只停在供应商凭据门槛上,dsh plugin remove 把依赖和这一行都干净移除。
0.2.0 不再支持 0.1.0-rc 线:上游把 CallId 改名为 ToolCallId,并把 JsonValue 从 dsh-session 挪走,对 0.1.0-rc.6 构建会直接失败。还留在那条线上的话请继续用本插件的 0.1.0。
另外提醒:npm 上 @deepseek-ai/* 的 latest 标签现在指向 0.1.5-rc.2,0.1.6 预发布在 alpha 标签上。手动安装 harness 相关包时请显式指定版本。
Harness 处于开发者预览期,官方明确说会有破坏性变更。契约一旦变动,本插件的测试会直接炸——因为它们是通过真实注册表执行真实调用,而不是 mock 瀑布。
开发
npm install
npm test # 61 个测试:纯单元测试 + 通过真实 ToolRuntime 的端到端测试
npm run typecheck
npm run build
dsh.compatibility.dshReleases 里的每个版本 CI 都会跑。本地复现某一个版本时,把整个 harness 家族钉到该版本再跑套件(package.json 和 lockfile 跑完会还原):
node scripts/pin-dsh.mjs 0.1.6-alpha.2
npm run typecheck && npm test && npm run build
不发包也能在真实 harness 上试:
dsh plugin --profile <名字> add /path/to/dsh-egress-guard
dsh --profile <名字> --dump-config # 能看到 "# == dsh-egress-guard" 这一层
许可证
链接
同类插件
toby-bridges/api-relay-audit★ 861
从 DeepSeek Harness 对 AI API 中转站和 LLM 代理运行本地安全审计,生成 Markdown 报告,覆盖提示词注入、模型替换信号、工具调用改写、错误泄漏、流完整性和按 profile 启用的 Web3 风险。
SeaOf0/dsh-redteam-model★ 646
面向授权安全研究的 DSH 合集:九个工作模式(redteam 总控、渗透测试、代码审计、二进制分析、攻防评估、免杀对抗、应急溯源、云安全攻防、CTF 解题)与十五个运行时插件,设置页管理台支持一键部署、安装、更新与卸载。
howmp/dsh-pentest★ 559
面向 DeepSeek Harness 的授权渗透模式:以探索链路记录目标、线索、资产与漏洞,并在 Web 中可视化展示。
PerryLink/dsh-auto-review★ 212
审批链上的第二模型自动审查:只读审查子代理返回带理由的 allow/deny 结构化裁决,默认 fail-closed。
NanmiCoder/dsh-auto-mode★ 164
在 Workspace Write 与 Full access 之间增加 Auto 权限档:日常操作留在官方 workspace-write 沙箱内,由当前会话模型复核升权与破坏性调用,精确的越界访问按次放行一次,意图不明时询问,命中关键路径则拒绝。
PerryLink/dsh-permission-rules★ 115
Claude Code 风格的声明式权限规则:按序 allow/deny/ask 的 YAML 规则,在 tools/pre-execute 瀑布上匹配工具名、参数、工作区路径与 agent 身份,带完整会话日志审计、干跑模式与热重载。
社区评论
评论公开保存在 GitHub Discussions。加载评论会连接 GitHub 和 Giscus;发表内容需要 GitHub 账号。