JohnXu22786/safety-net
编码 agent 破坏性命令拦截闸门:rm -rf / git reset --hard / push --force 执行前解析判定并要求人工确认(dsh 插件 + 通用 CLI)
Listed
0
Security
Bundle verified
What it does
Destructive-command interception gate for dsh: parses shell semantics, judges risk against 41 built-in rules, and holds irreversible rm -rf, git reset --hard, and git push --force style commands at a confirmation gate.
Best for
- Coding-agent workflows that need confirmation before destructive shell operations such as recursive deletion, hard resets, or forced pushes.
- Teams wanting semantic command analysis, configurable risk levels, and redacted audit records around supported shell entry points.
Not ideal for
- Workflows needing a true sandbox or privilege boundary; it only gates commands issued through supported integration points.
- Default-policy environments facing runtime-generated commands such as eval "$X"; content unavailable to static analysis may pass unless vigilant or fail-closed behavior is enabled.
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
Frequently Asked QuestionsFAQ
Use the verified command dsh plugin --profile default add github:JohnXu22786/safety-net in a DSH-enabled shell. The command resolves the public package metadata and keeps the plugin attached to the catalog identity shown on this page.
Compatibility follows the bundle and profile status shown above. If a profile is not detected, keep the plugin disabled there and check the repository documentation before enabling it in production.
The GitHub link and activity metadata are the source of truth for releases and maintenance. Revisit this page after a new release to confirm the catalog has observed the latest version.