dsh 破坏性命令拦截闸门:解析 shell 语义、依据 41 条内置规则判定风险,将 rm -rf、git reset --hard、git push --force 等不可逆命令挡在确认关卡之前。
安装
# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)
dsh plugin --profile web add github:JohnXu22786/safety-net
装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络,工具审批管不到它。GitHub 来源的插件还会在安装时执行构建脚本。请只安装可信来源,并尽量锁定 commit(github:owner/repo#sha)。
README
Barricade
A destructive-command interception gate for coding agents: it parses command semantics and judges risk before
rm -rf,git reset --hard,git push --forceand similar commands actually land, then requires human confirmation.
Barricade is a self-contained plugin/CLI with zero runtime dependencies (pure Node.js ESM), designed for any harness that "hands the shell over to an agent". It does not sandbox and does not limit capabilities; it does only one thing: hold irreversible operations at a confirmation gate — including those even a sandbox can't stop (git reset --hard discards the working tree, git push --force overwrites remote history, rm -rf deletes untracked files in the workspace).
Capabilities at a Glance
- Semantic-level command parsing: not string matching. Ships its own POSIX lexer that recognizes quotes, escapes, heredocs, command substitution
$(...), sub-shells and pipeline chains;bash -c "rm -rf /",sudo rm -rf /,eval "rm -rf /",echo $(rm -rf /)cannot slip through. - Per-command verifiers: git (reset/clean/push/checkout/branch/stash/restore — 13 dangerous forms, supporting long-flag unique prefixes and short-flag unbinding), rm (tiered by target scope: root/home/.git → fatal; outside workspace / dynamic targets → high; inside workspace → medium), dd/mkfs/shred/chmod/chown, find -delete, curl|sh, interpreter one-liners, fork bombs, PowerShell forced deletion — 41 built-in rules.
- Three levels:
relaxed/balanced(default) /vigilant, mapping severity → action (deny/ask/allow) tier by tier; undervigilant, unparseable inputs ask as needed (fail-closed). - Interactive confirmation: on a TTY it shows the command and matched rules, supporting run once / deny / allow for this session / allow permanently (written to policy) / show details; non-TTY environments always deny (fail-safe).
- Portable across harnesses: the verdict core is harness-agnostic (input
(command, cwd, level), output structured verdict); three integration forms to choose from: a dsh in-process plugin, a generic stdin-hook JSON contract, and agateshell wrapper. - Audit: interception and confirmation records are persisted as JSONL; secret-like content is automatically redacted.
How It Works
agent 准备执行命令
│
▼
┌─────────────────┐ ┌──────────────┐
│ 接入点(任一) │──▶│ 命令分析引擎 │
│ dsh 插件事件 │ │ 分词 → 分段 │
│ stdin-hook │ │ 拆包装 → 判定 │
│ gate 包装 │ └──────┬───────┘
└─────────────────┘ │
▼
┌─ 放行 ──▶ 命令执行
│
判定结果
│
└─ 需确认 ─▶ TTY 交互确认 ──▶ 执行/拒绝
非 TTY:拒绝(失败安全)
Key steps of the analysis engine:
- Tokenize: POSIX-style lexing (quotes/escapes/operators/heredoc bodies/command-substitution extraction); falls back to a coarse-grained pattern scan when input is over the limit or unparseable.
- Segment: splits command segments by
&&||;|&and sub-shells; trackscdexecution directories; each segment is judged independently, and any dangerous segment blocks the whole command. - Unwrap: recursively strips wrapper commands like
sudo/env/command/timeoutand embedded loads inbash -c/sh -c/su -c(depth limit 8; beyond the limit, ask as needed). - Verdict merge: fatal first; any deny → deny; any ask → ask; policy
overridescan adjust high/medium actions, but fatal rules cannot be downgraded.
Installation
Requires Node.js ≥ 18.13, no npm dependencies.
# 直接运行(无需安装)
node bin/barricade.js --help
# 作为命令行工具使用(可选)
npm link # 之后可直接使用 barricade 命令
Integrating with dsh (DeepSeek Harness)
This repository is a valid dsh bundle: package.json declares dsh.bundle, cordis.patch.yml is the config-layer patch, and plugin.js is the plugin entry point.
Installing in DSH
dsh plugin --profile demo add github:JohnXu22786/safety-net
Loading
# 在目标 profile 中安装本 bundle(本地目录或已发布的 npm 包名)
dsh plugin --profile web add ../dsh-barricade # 或 dsh plugin --profile web add dsh-barricade
# 启动
dsh --profile web
After loading, Cordis inserts the plugin line per cordis.patch.yml:
- insert:
- id: barricade
name: dsh-barricade
Plugin Interface
| Item | Value |
|---|---|
| Entry | plugin.js (main field), exports name / inject / apply(ctx, config) |
| Events | listens to the tool execution pipeline event tools/pre-execute (waterfall), intervening before the tool actually runs |
| Interception | throws BarricadeBlocked when a block verdict is produced; the tool call fails and the reason is visible to the model |
| Config | the config field in cordis.patch.yml, or a dsh --patch overlay |
Available config keys (all optional):
| Key | Default | Description |
|---|---|---|
mode |
"deny" |
deny: deny on match; ask: request human confirmation through the ctx.approval service; if confirmation is refused or the service is unavailable, treat as deny |
toolNames |
common shell tool name list | only intercept these tools; can also be overridden via the BARRICADE_TOOLS env var (comma-separated) |
commandPath |
"args.command" |
dot-path to the command text in the tool call; compatible with input.command / command and other shapes |
level |
policy file | relaxed / balanced / vigilant |
Example (written into the profile's cordis.patch.yml or a --patch overlay):
- insert:
- id: barricade
name: dsh-barricade
config:
mode: ask
toolNames: [bash, run_code, run_command]
Note: dsh is currently in developer preview and its interfaces may evolve.
applydefensively recognizes tool-call shapes (name/tool,args/input, etc.) and probes the various calling forms ofctx.approval; if any form is unavailable it falls back to deny, keeping fail-safe. If the upstream event contract changes, just adjust the event name and field paths inplugin.js.
Other Harness Integration
The verdict core depends on no harness; pick any of the three forms:
① stdin-hook contract (for harnesses that support "run a hook before tool invocation", such as PreToolUse-style hooks):
stdin : {"command": "<待执行命令>", "cwd": "<可选>"} # 或纯命令文本
stdout : {"action": "allow|ask|deny", "severity": ..., "matches": [...], "warnings": [...]}
exit : 0(正常输出判定);加 --exit-on-block 时拦截退出 1
Example (point the hook command at node <本目录>/bin/barricade.js hook):
echo '{"command":"git push --force origin main"}' | node bin/barricade.js hook
# {"command":"git push --force origin main","action":"ask","severity":"high",
# "reason":"强制推送覆盖远端提交历史,可能造成他人工作丢失","matches":[...],"warnings":[]}
② gate wrapper (swap the harness's shell for barricade gate -- <command>): executes after terminal confirmation; non-terminal environments are blocked outright.
③ in-process reuse: createInterceptor(config) returns a pure verdict function callable from any Node in-process harness (see the comments at the top of plugin.js).
CLI Usage
barricade <子命令> [选项]
analyze [--json] <命令> 分析并输出判定(不执行;退出码恒 0)
check [--json] [--quiet] <命令> 判定;放行退出 0,拦截退出 1
gate -- <命令> 分析 + 交互确认 + 执行
hook 见上文 stdin-hook 契约
policy --show [--json] 显示合并后的策略
policy --validate [--policy F] 校验策略文件
rules [--json] 列出内置规则
audit [--tail N] 查看审计记录
-c, --command <命令> --stdin 命令输入方式
--level <等级> --policy <F> 临时等级 / 指定策略文件
--json --quiet --exit-on-block
-h, --help -v, --version --tail <N>
Examples:
barricade check -c "rm -rf /" # 退出 1,打印拦截原因
barricade analyze --json -c "git reset --hard"
barricade gate -- "npm run build" # 终端下交互确认
Policy Configuration
Config files: user-level ~/.barricade/barricade.json (BARRICADE_HOME to change), project-level .barricade.json (current directory, takes precedence over user-level). Both are JSON; missing/corrupt fields rescue-fall back to defaults with a warning — a policy file can never interrupt your workflow.
{
"version": 1,
"level": "balanced",
"failClosed": false,
"allowlist": ["git status", "git log", "ls -la"],
"overrides": { "git/tag-delete": "allow" },
"rules": [
{
"id": "custom/dropdb-force",
"command": "dropdb",
"args": ["--force"],
"severity": "high",
"reason": "强制删除数据库不可恢复"
}
],
"confirmation": { "sessionMemory": true, "timeoutSeconds": 0 }
}
| Field | Description |
|---|---|
level |
relaxed (medium allowed) / balanced (medium asks) / vigilant (+ unparseable input asks as needed) |
failClosed |
require confirmation even when a command cannot be parsed |
allowlist |
prefix allowlist (git status allows git status --porcelain) |
overrides |
adjust per-rule-id actions: allow / ask / deny / off; fatal rules cannot be downgraded |
rules |
custom rules: command + optional subcommand + any arg match (short-flag unbinding supported) |
confirmation.timeoutSeconds |
interactive confirmation timeout (seconds); timeout counts as deny; 0 means no timeout |
Environment variables (raise-only, never lower):
| Variable | Description |
|---|---|
BARRICADE_HOME |
data directory (policy, audit logs), default ~/.barricade |
BARRICADE_POLICY |
specify a user policy file path |
BARRICADE_LEVEL |
raise the level (only takes effect when higher than the file level) |
BARRICADE_FAIL_CLOSED=1 |
enable fail-closed |
BARRICADE_CONFIRM_TIMEOUT |
confirmation timeout seconds |
BARRICADE_TOOLS |
comma-separated list of tools the dsh plugin intercepts |
BARRICADE_NO_COLOR / NO_COLOR |
disable colored output |
Interactive Confirmation
⚠️ Barricade 需要确认此命令 [高危]
命令: git push --force origin main
• git/push-force — 强制推送覆盖远端提交历史,可能造成他人工作丢失
[y] 执行一次 [n] 拒绝 [s] 本会话放行 [a] 永久放行 [d] 详情 [q] 退出
>
awrites the rule into the user policy file (overrides); fatal rules cannot be allowed permanently.srecords the rule into this invocation's session set; within a singlegatecall it confirms only once, sosis equivalent toy; it can take effect across calls when the same session set is reused in-process.- Control characters are escaped and the command truncated before display, preventing terminal injection (the verdict text and audit logs are handled the same way).
Built-in Rules (excerpt)
| Rule id | Severity | Description |
|---|---|---|
fs/rm-root / fs/rm-home |
fatal | delete root / home directory |
fs/rm-git |
fatal | delete/write/move .git internals |
fs/mkfs-device / fs/dd-device |
fatal/high | format or write block devices (safe targets such as /dev/null excluded) |
fs/rm-outside / fs/rm-dynamic / fs/rm-workspace |
high/high/medium | rm -rf target scope tiers |
fs/find-delete / fs/shred / fs/chmod-recursive / fs/chown-recursive |
high/high/medium/medium | bulk or recursive destructive operations |
git/reset-hard / git/clean-force / git/push-force / git/push-delete |
high/high/high/medium | overwrite history, discard uncommitted changes, delete remote branches |
git/checkout-force / git/checkout-discard / git/switch-force / git/restore-worktree |
high | discard working-tree changes |
git/branch-delete-force / git/stash-drop / git/stash-clear / git/tag-delete |
high/high/high/medium | unrecoverable ref/stash operations |
git/fetch-force / git/ssh-env |
medium/high | overwrite remote refs / GIT_SSH* combined with network subcommands |
shell/curl-pipe-sh / shell/fork-bomb / interp/embedded |
high | remote-script piping, fork bombs, interpreter-embedded deletion code |
sys/shutdown / sys/reboot / sys/powershell-remove / sys/cmd-del |
high/high/medium/medium | system-level operations |
The full list and action mapping: barricade rules.
Security Model and Known Boundaries
- Not a sandbox, and not a privilege boundary. It intercepts "commands the harness issues through supported entry points"; bypassing the integration (e.g. writing files directly with an editor tool, executing manually outside a container) is out of protection scope.
- Inherent limits of static analysis: runtime-only content such as
bash <unknown script>andeval "$X"cannot be inspected — undervigilantthey require confirmation; under the default level they pass (tightenable withfailClosedor custom rules). - Analysis handles command text with POSIX path semantics, independent of the running platform; on Windows,
gateruns viacmd /c, while the command itself is still parsed with POSIX syntax. - Input size limit 128 KiB and nesting depth limit 8; beyond the limits it falls back to coarse-grained scanning or asks as needed, preventing malformed input from stalling analysis.
Development
node --test # 或 npm test;测试用例见 test/ 目录
Structure:
bin/barricade.js CLI 入口
plugin.js dsh(Cordis)插件入口
src/
tokenizer.js 词法分析(引号/heredoc/命令替换)
analyzer.js 命令段组织、包装拆解、分命令判定
rules.js 内置规则库与等级映射
verdict.js 判定合并模型
policy.js 策略加载与挽救式校验
prompt.js 交互确认
audit.js 审计日志(脱敏)
executor.js gate 执行器
cordis.patch.yml dsh 配置层补丁
examples/ 示例配置与 hook 契约样例
test/ 181 个测试用例
License
链接
同类插件
superdesigndev/treg★ 425
给 Agent 的工具目录:按「要做的事」检索约 2,600 个外部接口(SEO 与 SERP、外链、社交、人物与公司信息补全、广告库、抓取),查看参数与单次调用价格后直接调用,凭据由服务端注入。附带技能,MCP 行在未设置 TREG_TOKEN 前保持禁用。
Lum1104/dsh-browser★ 198
Chrome 侧边栏扩展,让 DSH 直接操控你的浏览器,无需视觉能力。
zhaoolee/notes★ 142
将 DSH 对话导出为锤子便签风格 PNG,或在配置的账号工作区中新建和更新 Markdown 便签。
liustack/modsearch★ 111
纯文本 agent 的联网搜索桥:搜索网页与 X,返回结构化 JSON 证据(search/fetch/引用)。
taxueseek/argo★ 91
专为 agent 打造的搜索工具:多语言,覆盖中文/英文/学术/代码/购物/金融/新闻/百科。
Vladimir-Human/ru-marketplace-mcp#dsh★ 63
面向俄罗斯十家电商平台的技能与可选 MCP 行:跨 Wildberries、Detsky Mir、Yandex Market 比价,以及各平台的搜索、商品卡与评论。安装后 13 个技能立即可用;两行 MCP 默认关闭,需将 RU_MARKETPLACE_MCP_DIR 指向本地克隆,该克隆需要 Python 3.12+ 与 uv。