前言¶
DeepSeek Harness(DSH)在工具输出侧会按 output.schema 校验;对不上就抛 ToolOutputError。工具输入侧的 parameters 主要写进模型提示词,host 默认不会在调用前按 schema 拦一层。类型错了往往一路进工具函数体,最后在 Node 里变成裸 TypeError——例如 The "path" argument must be of type string、p.replace is not a function。对 5 个已发布插件做 148 次参数模糊调用时,有 47 次以这类错误结束,来自 12 个不同入口点。
@bushizhanghan/dsh-arg-guard 是维护者 bushizhanghan 发布的 DSH 插件,分类为 admin-security。它在 host 唯一的入参关卡 tools/pre-execute 瀑布里,用工具自己声明的 parameters 做入参校验;违规则拒绝,并把确切的 JSON 路径与期望类型交给模型,便于改参数而不是对着堆栈猜。
这是什么¶
一句话:在每次工具执行前,按工具定义的 JSON Schema 风格 parameters 校验实参;通过则放行,不通过则 deny(或 warn 只记日志)。
- 仓库:bushizhanghan/dsh-arg-guard
- 社区目录:SkillHub 插件页
- 许可证:MIT(见仓库)
- 当前包版本(package.json):0.1.0;运行环境要求 Node
>=22
插件只读:不写磁盘、不发网络请求;统计计数器仅在内存中。
缺口在 host 里的位置¶
下面事实来自对 host 源码的核对(README 中引用),不是推测:
| 位置 | 事实 |
|---|---|
_dsh-tools.js:3321 |
tools/pre-execute 瀑布是唯一的入参关卡 |
_dsh-tools.js:3345 |
拒绝理由会原样变成模型看到的 Error: <reason> |
_dsh-tools.js:3091 / 3107 |
get / resolveExecution 能拿到带 parameters 的工具定义 |
| 输出侧 | output.schema 已有强制校验 |
因此:schema 写给模型看,默认并不按同一套规则检查入参;各插件作者若手写 typeof 守卫,容易漏。本插件把校验集中到 host 瀑布里,并用统一的理由格式回给模型。
核心功能¶
校验行为¶
注册 tools/pre-execute 处理器,对每次调用根据该工具的 parameters 判定 allow 或 deny(warn 模式下只记录仍放行)。
拒绝理由格式固定为:<工具名>.<JSON 路径>: expected <类型>, got <类型> (<值>);根级错误省略点号。
README 中 publish_gate 的真实示例:
{"dir":123} → deny: publish_gate.dir: expected string, got number (123)
{"mode":"fix"} → deny: publish_gate.dir: required but missing
{"dir":"E:/p","mode":"slow"} → deny: publish_gate.mode: expected one of "check", "fix", got string ("slow")
{"dir":"E:/p","extra":1} → deny: publish_gate.extra: unexpected property (allowed: dir, mode)
{"dir":"E:/p","mode":"fix"} → allow
支持的 schema 规则¶
| 规则 | 说明 |
|---|---|
| 原始类型 | string / number / integer / boolean / null |
| 类型联合 | 如 type: ["string","null"] |
| 必填 | required;undefined 等同未传 |
| 枚举 / 常量 | enum、const |
| 嵌套对象 | properties 递归,路径用点号连接 |
| 数组 | items(对象或元组) |
| 封闭对象 | additionalProperties: false(patternProperties 命中键可放行) |
| 组合 | oneOf / anyOf / allOf |
明确不做的校验¶
- 不做类型强转:例如 schema 要求
integer时,字符串"3"视为错误。 - 未实现的 JSON Schema 关键字一律忽略:如
$ref、if/then/else、format、dependencies等——看不懂则不据此拒绝。 - 不校验输出(host 已负责)。
- 不跨进程:只作用于同一 host 内注册的工具。
Agent 辅助工具¶
| 工具 | 作用 |
|---|---|
arg_guard_status |
查看 hook 是否挂上、mode、skip、计数器(checked/allowed/denied/warned/skipped/errors)、最近 10 条违规 |
arg_guard_check |
对 {tool, args} 干跑,返回与真实 hook 一致的 verdict 与理由,不执行、不计数 |
典型用法:某次调用被拒后,用相同参数干跑查明原因;或在发请求前自检,减少往返。
安装与启用¶
在 profile 为 desktop 时,安装命令(须与资料原文一致):
dsh plugin --profile desktop add @bushizhanghan/dsh-arg-guard
安装后重启 DSH 生效。
配置¶
在插件 config 中可设置:
- id: arg-guard
name: "@bushizhanghan/dsh-arg-guard"
config:
enabled: true # 总开关,默认 true
mode: deny # deny = 拦截;warn = 只记录、放行
skip: [] # 不检查的工具名,例如 [bash]
上线顺序建议:先用 mode: warn 跑一段时间,通过 arg_guard_status 查看 violations 是否有误报(工具声明的 schema 比真实契约更严时可能误报),确认后再切 deny。
安全与误拦策略¶
插件第一原则是:守卫弄坏的调用,比没有守卫更糟。
- 处理器整体包在
try/catch中,异常时 fall through 到allow。 - 解析不到定义、未声明
parameters.properties、schema 畸形、类型名不认识等情况 →allow。 - 可通过
skip放行指定工具名,或用mode: warn先观测。
校验核心在 lib/engine.js 的纯函数 validateArguments;README 称其有 38 个测试用例直接断言,含「定义查询抛错仍放行」等路径。开发侧可运行:
npm test # node --test
适用场景与注意¶
适合谁:在 DSH 上开发或运维多工具智能体、希望把「错类型」从 Node 堆栈前移到可读的拒绝理由;尤其当工具 parameters 已写完整、希望 host 统一 enforcement 时。
使用前请知悉:
- 插件与当前 DSH 进程同权限运行;安装前应自行阅读 GitHub 源码 与 LICENSE。
- 社区目录 SkillHub 为独立生态站点,与 DeepSeek / 幻方无官方从属关系;DSH 理念是「一切皆插件」,按需从目录或 GitHub 安装即可。
- 不认识的 schema 关键字会被忽略,不能替代对复杂契约(大量
$ref等)的完整 JSON Schema 校验器。
结尾¶
dsh-arg-guard 补上 host 在工具入参侧的空缺:在 tools/pre-execute 按各工具自报的 parameters 校验,把裸 TypeError 换成带 JSON 路径的类型说明,并可通过 warn / skip 与 arg_guard_check 控制风险。
- 目录页:https://www.skillhub.cn/plugins/bushizhanghan/dsh-arg-guard
- GitHub:https://github.com/bushizhanghan/dsh-arg-guard