dsh-ast-guard
v0.1.0
Published
基于 AST 的 DeepSeek Harness 安全防护插件 — 解析 Bash 命令与文件操作,拦截危险操作(移植自 pi-ast-guard)
Maintainers
Readme
dsh-ast-guard
基于 AST 的 DeepSeek Harness 安全防护插件——解析 Bash 命令与文件操作,在工具执行前拦截危险操作。 移植自 pi-ast-guard v1.1.2(原 pi-damage-control),MIT 许可。
- 命令语义规则:
git reset --hard、rm -rf、drop database等由 just-bash AST 精确识别, 对文本 / Markdown / heredoc 内容零误报。 - 路径规则:
zeroAccess/readOnly/noDelete,glob 匹配(*不跨段、**任意深度、$CWD、outsideWorkdir、~)。 - 动作:
allow/ask/block(默认ask),优先级block > ask > allow; 策略三层叠加:内置默认 → 全局~/.dsh/ast-guard.yml→ 项目.dsh/ast-guard.yml。 - 会话决策:弹窗四选(同意一次 / 本会话允许 / 本会话拒绝 / 拒绝一次),30s 超时或关闭弹窗 = fail-closed; 粗粒度规则(工作区外、根锚定深度 ≤2、首段通配)会要求输入作用域路径(自动校验与规则相交、目录存在)。
- DNA 模式(
/ag-dna):ask自动应答(工作区内/外 × 读/写 四参数readInside/readOutside/writeInside/writeOutside), 工具黑白名单,累计自动拒绝 ≥maxViolations强制中断回合;提醒注入 system prompt。 - 与 DSH 沙箱联动:ast-guard 放行后,同工具在 120s 窗口内触发的沙箱升级审批(
sandbox_permissions重试) 自动批准,避免二次弹窗。
安装
# 1. 构建(需要 node >= 22)
pnpm install && pnpm build
# 2. 加入 web profile(bundle 声明 dsh.bundle.patch 会自动挂载 ast-guard 行)
dsh plugin --profile web add ../dsh-ast-guard # 或把 dsh-ast-guard 加入 profile 的 dsh.profile.bundles
# 3. 重启 dsh web如需在 Windows 上用 Git Bash 执行命令,一并安装
dsh-bash-terminal,
并在其设置或行配置中把默认终端选为 Git Bash(bash -lc 语法与 ast-guard 的 bash AST 完全兼容;
若保持 PowerShell 后端,PowerShell 命令的解析失败会被自动放行,不弹窗)。
⚠️ Git Bash × DSH 沙箱兼容性(实测):msys2 bash 需要创建信号管道,在
workspace-write沙箱的受限令牌下无法启动(couldn't create signal pipe, Win32 error 5, 退出码 0xC0000142)。因此 Git Bash 后端只能在danger-full-access模式(或 wsl 后端) 下使用;workspace-write模式下请使用 PowerShell 后端。
⚠️ Windows 上的 pwsh 绕过面(发布建议):win32 上官方
pwsh工具与shell工具并存,模型可自由调用 pwsh;PowerShell 原生命令(Remove-Item、Set-Content等)无法被 bash AST 解析,会被自动放行(绕过命令与路径规则; POSIX 语法子集如git reset --hard仍受拦截)。如需关闭该面,在 profile 的cordis.patch.yml中禁用官方工具即可,命令将只走shell(gitbash)后端:- id: tool-pwsh disabled: true
配置
全局策略:~/.dsh/ast-guard.yml(首次启动自动生成模板)。
项目策略:<项目>/.dsh/ast-guard.yml。
settings:
language: auto # zh | en | auto
parseFailure: ask # 无法解析时的动作(allow/ask/block)
showStatus: true
extraDirs: [] # 额外视为工作区内的目录
dna:
readInside: allow
readOutside: allow
writeInside: allow
writeOutside: block
maxViolations: 3
allowTools: [] # 非空时为白名单模式
blockTools: []
extraPrompt: ""
rules:
- id: block-git-reset
type: command
match:
command: git
subcommand: reset
argsAny: ["--hard"]
action: ask
- id: protect-secrets
type: path
match:
path:
any: ["**/.env", "**/.env.*"]
action: blockrules 按 id 覆盖(上层同名规则整体替换下层),不同 id 全部保留;
settings 深度合并。优先级偏移:内置 -0.6、全局 -0.3、项目 0。
命令
| 命令 | 说明 |
|------|------|
| /ag-status | 重新加载策略并显示状态面板(DNA 状态 + 最近 10 条会话决策) |
| /ag-dna [on\|off] | 开启/关闭 DNA(Do Not Ask)模式 |
| /ag-forget 1,3 | 按序号清除会话决策 |
pi 的
/ag:xxx冒号命令名在 DSH 中不合法(/^[a-z][a-z0-9_-]*$/),故改用连字符。
拦截面(工具适配)
| 工具 | 评估方式 |
|------|----------|
| bash / shell(gitbash、wsl 后端) | bash AST 命令规则 + 文件意图路径规则 |
| pwsh / shell(powershell 后端) | 尽力用 bash 解析;解析失败自动放行 |
| terminal(send) | 输入行按 bash 分析 |
| read / read_image | 路径规则(读) |
| write / edit / str_replace_editor | 路径规则(写) |
| glob / grep | 路径规则(读,目录) |
与 pi-ast-guard 的差异(移植说明)
- 拦截点:pi
tool_call事件 → DSHtools/pre-execute瀑布(prepend,返回allow/denygate)。 - 取消:pi
ctx.abort()→agent.cancel({ kind: "hook", reason })。 - 弹窗:pi
ctx.ui.select/input→ctx.userQuestions.ask(4 选项单选 + 自定义文本框输入作用域; 无 UI / 子代理 / 超时 = fail-closed 拒绝)。DSH 审批本身只有单次放行语义,会话级决策由本插件自己维护。 - 状态面板:pi
setStatus/setWidget常驻面板 →/ag-status命令文本输出。 - DNA 提醒:pi 改写 provider payload → DSH
systemPrompt.section动态增删。 - 策略路径:
.pi/ast-guard.yml→.dsh/ast-guard.yml;全局~/.pi/agent/→~/.dsh/。 - 持久化:会话决策与 DNA 状态为内存态(v1),不跨重启;重启后自动重置。
- 新增:approval 联动(见上)、
shell/terminal工具映射、子代理场景 fail-closed。
开发
pnpm typecheck # tsc --noEmit
pnpm build # tsc → lib/
pnpm test # vitest run(宿主无关模块的单元测试)