DeepSeek Harness 插件

JohnXu22786/safety-net

Star 数 ★ 0 分类 工具与能力 收录于 2026-08-16

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 --force and 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; under vigilant, 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 a gate shell 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:

  1. 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.
  2. Segment: splits command segments by && || ; | & and sub-shells; tracks cd execution directories; each segment is judged independently, and any dangerous segment blocks the whole command.
  3. Unwrap: recursively strips wrapper commands like sudo / env / command / timeout and embedded loads in bash -c / sh -c / su -c (depth limit 8; beyond the limit, ask as needed).
  4. Verdict merge: fatal first; any deny → deny; any ask → ask; policy overrides can 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. apply defensively recognizes tool-call shapes (name/tool, args/input, etc.) and probes the various calling forms of ctx.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 in plugin.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] 退出
>
  • a writes the rule into the user policy file (overrides); fatal rules cannot be allowed permanently.
  • s records the rule into this invocation's session set; within a single gate call it confirms only once, so s is equivalent to y; 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> and eval "$X" cannot be inspected — under vigilant they require confirmation; under the default level they pass (tightenable with failClosed or custom rules).
  • Analysis handles command text with POSIX path semantics, independent of the running platform; on Windows, gate runs via cmd /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

MIT

内容来自项目 README(GitHub)↗

链接

同类插件

查看整个分类 →