bash-vet-mcp
bash-vet-mcp
MCP server that vets LLM-emitted shell commands BEFORE execution — detects
rm -rfnested deep in chains, package-manager glob removal (apt remove '*nvidia*'),dd/mkfs/wipefsfilesystem destruction,chmod 777/chown -Rprivilege blast, network-exfil viacurl | bash, chainedshutdown/reboot, andgitdestructive ops. Sub-second, local, free, MCP-native — designed to be called inline by Claude Code / Cursor / Cline / OpenClaw before approving any agent-proposed command. Defensive complement to MCP shell-execution servers (MCPShell, mcp-shell, mcp-bash).
What it does
Production AI agents have a quiet failure mode in shell-command execution: the agent emits a chained command, the operator pattern-matches the start of the line, and a destructive fragment nested deep in the chain (&&, ;, |) gets executed by accident.
A working engineer (@chiefofautism, 158↑ / 135 RTs / 11.5K views) puts it more bluntly:
"claude code runs shell commands with YOUR permissions. it can rm -rf your repo. it can force push to main. it can drop your database. and it will do it confidently while telling you that he cleaned up the project structure"
The danger isn't just the destructive command — it's the confident misreport that follows. bash-vet attacks the first half of that pair (the "rm -rf / force-push / drop database" part); pair it with openclaw-output-vetter-mcp for the second half (the "while telling you he cleaned up the project structure" part).
Buried
rm -rf. r/LocalLLaMA "One bash permission slipped" (1,512↑) — operator approved a long chained command after recognizing the lede; the chain ended withrm -rf $UNSET_VAR/*which expanded torm -rf /*because the variable was empty. The classic xornullvoid wipeout wasapt remove '*nvidia*595*'cascading into critical-package removal.CVSS 10.0 in agent harnesses. r/devops "AI coding tools are now a CVSS 10.0 supply-chain risk" (130↑) cites Cursor CVE-2026-26268 and Gemini CLI CVSS 10.0 — both featuring
--yolomodes that ignore allowlists entirely and execute LLM-emitted commands without operator review.Network-exfil via curl-pipe-bash. Agents trained on installer documentation pattern-match
curl https://x.com/install.sh | bashas legitimate. Once the agent is the one fetching the URL, the operator has no way to inspect the script before it runs.Production-database deletion via API mutation. HN: "An AI agent deleted our production database. The agent's confession is below" (859↑ / 1,030 comments, May 2026) —
jeremyccranedocumented an agent issuingcurl -X POST .../graphql/v2 -d '{"query":"mutation { volumeDelete(volumeId: \"3d2c42fb-...\") }"}'against Railway with a token that had production-volume-delete privilege. No two-step confirmation, no environment scoping, no privilege boundary. Top community reply: "It's a privilege issue, not an execution issue." bash-vet catches the destructive curl-with-GraphQL-mutation pattern at command-approval time; pair with output-vetter'sverify_action_outcomefor the "agent's confession" half (the post-action misreport).
This MCP server runs the vetting inline before the command executes — no API key, no LLM-as-judge cost, sub-second:
> claude: vet this command before I run it: sudo apt remove '*nvidia*' && reboot
[MCP tool: vet_command_chain]
verdict: BLOCK
risk_score: 30
finding_count: 2
findings:
[HIGH] PACKAGE.APT_REMOVE_GLOB
snippet: sudo apt remove '*nvidia*'
description: apt removing packages by glob pattern — likely cascades into
critical-dependency removal
recommendation: Use exact package names. xornullvoid's nvidia-driver
wipeout was apt remove '*nvidia*595*'.
[HIGH] SHUTDOWN.CHAINED_REBOOT
snippet: && reboot
description: Chained reboot/shutdown after another command — cuts off the
operator's ability to react if anything went wrong (escalated MEDIUM→HIGH
because chain mode)
recommendation: Run shutdown/reboot as a separate command after manual
review.
summary: BLOCK — 2 finding(s); worst is HIGH (PACKAGE.APT_REMOVE_GLOB):
apt removing packages by glob pattern — likely cascades into critical-dependency
removalRelated MCP server: aperion-shield
Why bash-vet-mcp
Three things existing MCP shell-execution servers don't do:
Defensive complement, not yet-another-shell-executor. MCPShell, mcp-shell, mcp-bash all give the agent a
run_commandtool. bash-vet-mcp is the opposite shape: vet before execute. Pair it with one of those servers (or with Claude Code's built-in Bash tool) — the agent callsvet_commandbefore asking the operator to approve the run. If the verdict is BLOCK, the operator sees the destructive fragment surfaced before they pattern-match-approve.Sub-second + local + free. Pure-Python:
bashlexAST parse + regex pattern bank. No LLM-as-judge call, no API key, no per-call cost. Runs in CI, runs offline, runs at every agent turn without budget pressure.30 detection rules across 8 families, each with stable rule_id + severity + recommendation. Not "is this dangerous?" — exactly which rule fired, what severity, what the operator should do. This makes the response actionable at the agent loop level (block + retry with a different command) and at the human-review level (audit trail for compliance).
Built for the production AI operator who's already using Claude Code / Cursor / Cline / OpenClaw with shell access enabled, who's seen the failure mode at least once, and who wants the agent to vet its own emitted commands before asking for approval.
Tool surface
Tool | What it returns |
| Verdict (CLEAN / CAUTION / REVIEW / BLOCK / UNVERIFIED) + risk_score (0–100) + per-finding rule_id + severity + snippet + description + recommendation |
| Same as |
| Catalog of every rule the scanner applies — for coverage audits, compliance documentation, custom allowlist construction |
Resources:
bash-vet://demo/clean— sample CLEAN verdict (ls -la /home/user/projects && cat README.md)bash-vet://demo/dangerous— sample BLOCK verdict (apt-glob + chained reboot + curl|bash)bash-vet://demo/sneaky— sample SNEAKY chain mimicking the r/LocalLLaMA failure mode
Prompts:
vet-this-command(chain?)— diagnostic walkthrough; agent callsvet_command(or chain variant) on the most recent command + explains each findingaudit-script— line-by-line vet of a multi-line shell script + per-line verdict + overall script verdict
Detection rules (30 across 8 families)
Family | Rules | Severity range |
|
| MEDIUM → CRITICAL |
|
| MEDIUM → HIGH |
|
| HIGH |
|
| MEDIUM |
|
| HIGH |
|
| MEDIUM → HIGH |
|
| MEDIUM |
|
| LOW → CRITICAL |
Each rule has a stable rule_id (e.g., DESTRUCTIVE.RM_RECURSIVE_ROOT) + severity + pattern-kind tag + plain-English description + concrete recommendation. Call list_detection_rules to retrieve the full catalog.
Quickstart
Install
pip install bash-vet-mcpQuick verify (~30 seconds, no config)
After install, run the bundled demo to see bash-vet catch real adversarial commands:
bash-vet-mcp-demoYou'll see 6 representative shell commands vetted: typically 4 BLOCK (apt-glob removal, curl-pipe-bash, dd to device, chmod 777 -R /etc) + 1 REVIEW (rm-rf with empty env-var) + 1 CLEAN baseline. No external I/O, no API keys — safe to run anywhere. Useful first-30-seconds check before wiring up Claude Desktop.
Configure for Claude Desktop
Add to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"bash-vet": {
"command": "python",
"args": ["-m", "bash_vet_mcp"]
}
}
}Restart Claude Desktop. Test:
Resource
bash-vet://demo/dangerous— read it back to me.
The demo resource returns a sample CommandVetReport so you can verify the protocol wiring without authoring inputs.
Use it inline
> me: cd /tmp/build && make clean && rm -rf $BUILD_DIR/cache && git reset --hard HEAD~3
> claude: let me vet this before running.
[MCP tool: vet_command_chain]
verdict: BLOCK
findings:
[HIGH] DESTRUCTIVE.RM_RECURSIVE_VAR
snippet: rm -rf $BUILD_DIR/cache
description: rm -rf with environment variable — if the variable is empty
or unset, this becomes `rm -rf /cache` (or `rm -rf /` depending on glob).
recommendation: Replace with absolute path; or guard with [[ -n "$VAR" ]]
check before the rm. (escalated MEDIUM→HIGH because chain mode.)
[HIGH] GIT.RESET_HARD
snippet: git reset --hard HEAD~3
description: git reset --hard discards uncommitted local changes irreversibly.
recommendation: Confirm there are no uncommitted changes you want to keep.
(escalated MEDIUM→HIGH because chain mode.)
I'd recommend not running this as-is. Suggested rewrite:
cd /tmp/build && make clean
[[ -n "$BUILD_DIR" ]] && rm -rf "$BUILD_DIR/cache"
# commit/stash any work, THEN: git reset --hard HEAD~3Roadmap
Version | Scope | Status |
v1.0 | 24 rules across 8 families, bashlex AST + regex fallback, 3 tools / 3 demo resources / 2 prompts, GitHub Actions CI, PyPI Trusted Publishing, MCP Registry submission, 50+ tests | ✅ |
v1.0.3 | 30 rules (added | ✅ |
v1.1 | Optional shellcheck-as-backend mode for users who want the higher-quality static analysis on top of the destructive-pattern detection; per-rule severity overrides via config; allowlist mode (specific commands always pass) | ⏳ |
v1.2 | Sandboxed dry-run via | bash` is even attempted |
v1.x | Webhook emit on BLOCK verdict; CI integration to gate AI-generated commit-stage hooks that contain destructive patterns | ⏳ |
Need this adapted to your stack?
If your AI deployment uses a different shell harness, custom allowlists, language other than bash (PowerShell / fish / nushell), or specific compliance / auditing requirements — that's a Custom MCP Build engagement.
Tier | Scope | Investment | Timeline |
Simple | Custom rule set + tuned severity for your domain (e.g., extra DB-specific patterns) | $8,000–$10,000 | 1–2 weeks |
Standard | Multi-shell support (PowerShell / fish / nushell parsers + rule packs) + allowlist persistence | $15,000–$25,000 | 2–4 weeks |
Complex | Sandboxed dry-run backend (container-isolated execution to validate ambiguous cases) + audit-trail + CI integration | $30,000–$45,000 | 4–8 weeks |
To engage:
Email hello@temhan.dev with subject
Custom MCP Build inquiry — bash-vetInclude: 1-paragraph description of your stack + which tier
Reply within 2 business days with a 30-min discovery call slot
This server is part of a production-AI infrastructure MCP suite — companion to silentwatch-mcp (cron silent-failure detection), openclaw-health-mcp (deployment health), openclaw-cost-tracker-mcp (token-cost telemetry + 429 prediction), openclaw-skill-vetter-mcp (skill security vetting), openclaw-upgrade-orchestrator-mcp (upgrade safety), and openclaw-output-vetter-mcp (response grounding + swallowed-exception detection). Install all seven for full operational visibility.
How this fits in the agent-shell-execution ecosystem
Layer | Examples | Role |
Shell executor (existing MCP servers) | MCPShell, mcp-shell, mcp-bash, Claude Code's built-in | Run the command. Surface stdout/stderr to the agent. |
Vetter (this server) | bash-vet-mcp | Vet the command before the executor runs it. Surface destructive patterns to the operator. |
Static analyzer (host-side) | Catch shell scripting bugs (unquoted variables, etc.). Different scope from destructive-pattern detection. | |
Sandboxed dry-run (host-side) | Container-isolate suspect commands; observe behavior before allowing live execution. Heavier, slower, optional. |
Each layer is complementary. A command can pass shellcheck (no scripting bugs), pass bash-vet-mcp (no destructive patterns), and still need sandboxing if the agent's intent is unclear. We're aiming at the failure mode that's the most pattern-matchable and the most preventable: agent emits a chain with a destructive fragment buried in it, and the operator approves the chain because the lede looks fine.
Production AI audits
If you're running production AI and want an outside practitioner to score readiness, find the failure patterns already present (LLM-emitted shell commands being pattern P5.x in the catalog), and write the corrective-action plan:
Tier | Scope | Investment | Timeline |
Audit Lite | One system, top-5 findings, written report | $1,500 | 1 week |
Audit Standard | Full audit, all 14 patterns, 5 Cs findings, 90-day follow-up | $3,000 | 2–3 weeks |
Audit + Workshop | Standard audit + 2-day team workshop + first monthly audit included | $7,500 | 3–4 weeks |
Same email channel: hello@temhan.dev with subject AI audit inquiry.
Contributing
PRs welcome. The detection rules are intentionally pluggable — every rule is a tuple in the _RULES list in src/bash_vet_mcp/scanner.py. Adding a new rule is one tuple + one test case. The pattern-matching engine handles regex compilation, deduplication, severity scoring, and chain-mode escalation automatically.
Bug reports + feature requests: open a GitHub issue.
License
MIT — see LICENSE.
Related
Production-AI MCP Suite (Gumroad bundle) — this server plus 6 others in one curated 7-pack bundle
silentwatch-mcp — cron silent-failure detection
openclaw-health-mcp — deployment health
openclaw-cost-tracker-mcp — token-cost telemetry + 429 prediction
openclaw-skill-vetter-mcp — skill security vetting
openclaw-upgrade-orchestrator-mcp — upgrade safety + provider-side regression detection
openclaw-output-vetter-mcp — response grounding + swallowed-exception detection
AI Production Discipline Framework — Notion template, $19 — the methodology these MCP tools implement
SPEC.md — full server design
Built by Temur Khan — production AI engineer. Contact: hello@temhan.dev
Available Tools
3 toolslist_detection_rulesA
Return the catalog of every detection rule the scanner applies — rule_id, severity, pattern_kind, description, example_match. Use this to audit coverage, document detection scope to your compliance/security team, or build a custom allowlist. 30 rules across 8 families: DESTRUCTIVE / PACKAGE / PRIVILEGED / SHUTDOWN / EXFIL / DATABASE / GIT / SUSPICIOUS.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Since no annotations are provided, the description carries full burden. It transparently states the operation is a catalog retrieval (read-only) and provides details on contents (30 rules, 8 families). No side effects are implied, which is appropriate for a list tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences: first states purpose and output, second gives use cases and summary. No fluff, front-loaded with essential information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite no output schema or annotations, the description fully covers what the tool returns (fields, families, count). An agent can confidently invoke and interpret results.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has no parameters, so schema coverage is 100%. The description adds value by explaining the output details, meeting the baseline for a zero-parameter tool.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description explicitly states the tool returns a catalog of every detection rule with specific fields (rule_id, severity, pattern_kind, description, example_match). It clearly distinguishes from siblings (vet_command, vet_command_chain) which are likely for vetting, not listing.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear use cases: audit coverage, document detection scope, build custom allowlist. It implicitly suggests this is the go-to tool for listing rules, with no mention of alternatives for exclusion.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
vet_commandA
Vet a single shell command for destructive patterns BEFORE execution. Detects rm -rf nested in chains, package-manager glob removal (apt remove 'nvidia'), dd/mkfs/wipefs filesystem destruction, chmod 777 on system paths, curl|bash network-exfil, chained shutdown/reboot, git destructive ops (push --force, reset --hard), and DROP DATABASE / TRUNCATE via cli. Returns verdict (CLEAN / CAUTION / REVIEW / BLOCK / UNVERIFIED), risk_score (0-100), and per-finding rule_id + severity + recommendation. Sub-second, local, no API key. Use inline before approving any agent-proposed command.
| Name | Required | Description | Default |
|---|---|---|---|
| command | Yes | The shell command to vet (single command or pipeline) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description fully discloses the tool's behavior: it detects various destructive patterns, returns a verdict with risk_score and per-finding details, and operates sub-second locally with no API key. There are no annotations, so the description carries the full burden, which it meets.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the main purpose, followed by an enumeration of detections and return fields. Every sentence adds value, and there is no redundant information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the single parameter and no output schema, the description is complete: it explains what the tool does, what it detects, what it returns, and its performance characteristics (sub-second, local, no API key).
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% for the single 'command' parameter, so baseline is 3. The description does not add significant parameter-specific semantics beyond what the schema already provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: vetting a single shell command for destructive patterns before execution. It lists specific patterns detected, distinguishing it from sibling tools like vet_command_chain.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides clear context: 'Use inline before approving any agent-proposed command' and mentions performance characteristics. However, it does not explicitly contrast with the sibling tool vet_command_chain for when to use this vs. the chain variant.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
vet_command_chainA
Vet a chained / multi-statement shell command — same rules as vet_command, but escalates LOW→MEDIUM and MEDIUM→HIGH because destructive fragments nested deep inside a chain (after &&, ;, or |) are easier for the operator to overlook on a quick read. Use this for any command containing &&, ||, ;, or piped subshells. The exact failure mode this targets: r/LocalLLaMA 'one bash permission slipped' (1.5k upvotes) — agent proposed a chained command, operator pattern-matched the lede, missed rm -rf deep in the chain.
| Name | Required | Description | Default |
|---|---|---|---|
| command | Yes | The chained shell command to vet |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description must fully disclose behavior. It explains severity escalation (LOW→MEDIUM, MEDIUM→HIGH) and cites a real incident, but it does not specify what the vetting result is (e.g., risk score, flag, block) or how to interpret the output. This leaves some ambiguity.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is about 4 sentences and relatively concise. The anecdote about r/LocalLLaMA adds context but could be trimmed. Front-loads the core purpose. Slightly verbose but acceptable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given one required parameter, no output schema, and no annotations, the description adequately covers usage context and behavior difference from sibling. However, it lacks details on response format, error cases, or what success/failure looks like. For a simple tool, this might be sufficient, but more completeness would help.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 100% schema description coverage, baseline is 3. The description adds nuance by clarifying what 'chained' means (&&, ||, ;, piped subshells), but this largely echoes the schema's description of 'The chained shell command to vet' without adding significant new meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool vets chained shell commands and escalates severity compared to vet_command. It provides specific examples of chain operators (&&, ||, ;, piped subshells) and references a real-world failure mode, effectively distinguishing it from its sibling.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when to use: 'Use this for any command containing &&, ||, ;, or piped subshells.' The description also explains the rationale (operator oversight). It does not explicitly state when not to use, but the sibling name implies single commands should go to vet_command.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
3 tool updates
v1.0.3- First observed
list_detection_rules - First observed
vet_command - First observed
vet_command_chain
TDQS
Scored across 3 tools
Each tool has a distinct purpose: listing rules, vetting a single command, and vetting a chained command. Even vet_command and vet_command_chain are clearly differentiated by their handling of single vs. multi-statement commands.
All tool names follow a consistent verb_noun snake_case pattern (list_detection_rules, vet_command, vet_command_chain), making them predictable and easy to understand.
With 3 tools, the server is well-scoped for its purpose of vetting bash commands. Each tool serves a clear and necessary function without redundancy.
The tool set covers the core operations: inspecting available rules, vetting a single command, and vetting a chained command. There are no obvious gaps for the stated use case of inline command safety checks.
Maintenance
Related MCP Connectors
Security firewall for AI agents — scans MCP calls for injection, secrets, and risks.
Security scanner for MCP servers. Detect vulnerabilities, prompt injection, and tool poisoning.
MEOK MCP Hardening MCP — automated security red-team for any MCP server. Maps OWASP LLM Top 10
Paid remote MCP for LLM security scans, jailbreak checks, analytics, checkout, and readiness.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceRuntime safety guardrails for AI coding agents. Checks file access, validates shell commands, and scores your repo's AI safety — all via MCP.4 npm8MIT

aperion-shieldofficial
FlicenseAqualityAmaintenanceLocal guardrail proxy for AI coding agents. Wraps any MCP server (stdio or HTTP/SSE) and blocks destructive tool calls before they execute, with TOFU catalog pinning against rug pulls and tool-poisoning/result-injection scanning. Single Rust binary, Apache-2.0.148-- AlicenseAqualityFmaintenanceAdvanced shell command execution for AI agents — a Model Context Protocol (MCP) server with security policy engine, process lifecycle management, bounded output capture, POSIX signals, and token-efficient responses.62Creative Commons Attribution Non Commercial 4.0 International
- AlicenseNot gradedqualityCmaintenanceMCP server that vets package installations and shell commands to block dangerous actions by AI coding agents.5 npm1MIT