MCP stdio ShellGuard

السجل الرسمي الأمن

Defense-in-depth for MCP stdio servers: shell-injection guard, AST audit CLI, RCE blocking.

التثبيت

أضف هذا إلى إعدادات MCP في عميلك (Claude Desktop: claude_desktop_config.json، وCursor: ‏.cursor/mcp.json، ويستخدم VS Code وغيره الصيغة نفسها «mcpServers»).

NPM package mcp-stdio-shellguard
Claude Code
claude mcp add mcp-stdio-shellguard -- npx -y mcp-stdio-shellguard@0.1.2
إعداد JSON (Claude Desktop وCursor وVS Code)
{
    "mcpServers": {
        "mcp-stdio-shellguard": {
            "command": "npx",
            "args": [
                "-y",
                "mcp-stdio-shellguard@0.1.2"
            ]
        }
    }
}

التوثيق

مأخوذ من ملف README للمشروع على GitHub ويُحدَّث أسبوعيًا. تفتح الروابط على GitHub.

المحتويات
  1. mcp-stdio-shellguard
  2. Install
  3. What it gives you
  4. Tools (reference server)
  5. Sandbox profiles
  6. Trust tiers
  7. Library quickstart
  8. Audit CLI
  9. Anti-pattern library (12 rules)
  10. Pragmas
  11. Why this exists
  12. See also
  13. License

Part of the StudioMeyer MCP Stack — Built in Mallorca 🌴 · ⭐ if you use it

mcp-stdio-shellguard

Defense-in-depth bundle for MCP stdio servers. Wraps child_process.exec/spawn with allowlist + sandbox + replay-detection, plus an AST audit CLI (mcp-shellguard-audit) that scans MCP server sources for unsanitized shell calls. Closes the Ox-Security MCP stdio-RCE class (200k vulnerable servers, May 2026 disclosure).

  • MCP spec: 2025-06-18
  • SDK: @modelcontextprotocol/sdk ^1.29.0
  • Node: >= 20
  • License: MIT
  • Author: Matthias Meyer (StudioMeyer)

Install

npm install mcp-stdio-shellguard

Or run the audit CLI directly without installing:

npx -y -p mcp-stdio-shellguard mcp-shellguard-audit scan ./src

What it gives you

Three layers, opt-in piecewise:

  1. Library API — drop-in guardExec / guardSpawn you call from your own MCP server. Default-deny allowlist, sandbox profiles, replay window.
  2. Audit CLI — mcp-shellguard-audit scan <path> walks the AST, reports 12 anti-patterns from LOW (no timeout) to CRITICAL (exec(\...${userInput}...\)).
  3. Reference MCP server — mcp-stdio-shellguard-demo exposes 8 tools so the MCP Inspector / Claude Desktop can drive the bundle directly.

Tools (reference server)

ToolTypePurpose
guard_execdestructiveDefended child_process.exec. Forces args[] vector, allowlist + sandbox + replay. Returns stdout, stderr, exitCode, canonicalHash, isReplay, trustTier.
guard_spawndestructiveDefended child_process.spawn. Returns SHA-256 hashes of stdout/stderr instead of full bodies. Hard-rejects shell:true.
register_allowlistmutatingRegister a tool name with executable + args regex. Without registration the default-deny applies.
audit_sourceread-onlyScan a TS/JS path for shell-injection anti-patterns. Returns AuditFinding[] + summary.
audit_reportread-onlyFormat an audit result as markdown / json / SARIF 2.1.0.
replay_checkread-onlyCompute canonical SHA-256 hash for an invocation and report whether it's already in the replay window.
sandbox_statusread-onlyReport active sandbox profile + concrete limits + cgroup-v2 active flag.
trust_tierread-onlyDerive LOW/MEDIUM/HIGH/CRITICAL tier for a registered tool plus improvement hints.

Sandbox profiles

ProfileTimeoutMax stdoutMax stderrFD budgetcgroup-v2
strict5 s1 MB256 KB32yes (cpu/memory)
standard (default)30 s10 MB1 MB256yes
permissive5 min100 MB10 MB1024no

Caller can tighten via timeoutMs / fdBudget per call. Caller cannot widen beyond the profile.

Trust tiers

TierCondition
LOWtool not registered (default-deny)
MEDIUMregistered but argsPatterns empty (any args allowed)
HIGHargsPatterns set but sandbox or replay tracker inactive
CRITICALargsPatterns + sandbox + replay all active

Lift LOW → CRITICAL by registering the tool + setting argsPatterns + running through guardExec/guardSpawn (which always activate sandbox + replay).

Library quickstart

import {
  AllowlistRegistry,
  ReplayWindow,
  guardExec,
} from "mcp-stdio-shellguard";

const registry = new AllowlistRegistry();
const replay = new ReplayWindow();

registry.register({
  toolName: "git-log",
  executable: "/usr/bin/git",
  argsPatterns: ["^log$", "^--oneline$", "^-n$", "^\\d+$"],
  sandboxProfile: "strict",
});

const result = await guardExec(
  {
    toolName: "git-log",
    command: "/usr/bin/git",
    args: ["log", "--oneline", "-n", "10"],
  },
  { registry, replay },
);

console.log(result.stdout); // → commit lines
console.log(result.trustTier); // → "CRITICAL"
console.log(result.canonicalHash); // → 64-char SHA-256

Audit CLI

mcp-shellguard-audit scan ./src
mcp-shellguard-audit scan ./src --format sarif --output audit.sarif
mcp-shellguard-audit scan ./src --severity-floor HIGH    # CI gate

Exit codes:

  • 0 clean (no findings at-or-above floor)
  • 1 findings present
  • 2 parse / IO errors

Custom ignoreGlobs passed to scanPath or the audit_source MCP tool accept at most 128 strings. Each string is limited to 1024 UTF-16 code units and 16 unescaped opening grouping characters ((, {, [). Inputs above these budgets raise a controlled error before matching.

Anti-pattern library (12 rules)

IDSeverityTriggers on
exec_template_literal_with_inputCRITICALchild_process.exec(\ls ${x}\)
exec_dynamic_stringCRITICALchild_process.exec(cmd)
exec_sync_dynamic_stringCRITICALchild_process.execSync(cmd)
eval_near_child_processCRITICALeval(...)
function_constructor_near_child_processCRITICALnew Function(...)
spawn_dynamic_file_argsHIGHspawn(bin, userArgs)
exec_file_dynamicHIGHexecFile(bin, ...)
shell_true_optionHIGH{ shell: true }
os_system_equivalentHIGHDeno.run / Bun.spawn
spawn_literal_dynamic_argsMEDIUMspawn('git', userArgs)
unbounded_bufferLOWexec without maxBuffer
missing_timeoutLOWexec/spawn without timeout

The scanner resolves renamed child_process bindings before matching, so the dangerous shapes below are caught even when the call goes through an alias rather than a literal child_process.exec:

  • const execAsync = promisify(exec); execAsync(...${x})
  • import cp from "node:child_process"; cp.exec(...${x})
  • const { exec: sh } = require("child_process"); sh(...${x})
  • import { exec as run } from "node:child_process"; run(...)

Synchronous variants (spawnSync, execFileSync) share their async rules, and shell_true_option also fires on a string shell ({ shell: "/bin/sh" }) or a dynamic shell value — not just the literal { shell: true }. A promisify of a non-child_process function, a destructure off another module, and { shell: false } stay clean (no false positives).

Pragmas

  • // shellguard:ignore-next-line — suppress one finding
  • // shellguard:ignore-file — suppress whole file (rare; prefer per-line)

Why this exists

Ox-Security disclosed (2026-05) that 200k+ MCP stdio servers wrap child_process.exec with template literals carrying user input straight from LLM tool args. LiteLLM v1.83.6 was the canonical example (CVE patched in 1.83.7). This bundle is the defensive-security counterpart: a drop-in guard + scanner that closes the class. Inspired by AWS Linux seccomp + Chromium sandbox tiers.

See also

License

MIT — Copyright (c) 2026 Matthias Meyer (StudioMeyer)

الأسئلة الشائعة

ما هو MCP stdio ShellGuard؟

Defense-in-depth for MCP stdio servers: shell-injection guard, AST audit CLI, RCE blocking.

كيف أثبّت MCP stdio ShellGuard؟

يعمل على جهازك. في Claude Code: claude mcp add mcp-stdio-shellguard -- npx -y mcp-stdio-shellguard@0.1.2. وفي العملاء الآخرين، الصق إعداد JSON من هذه الصفحة في إعدادات MCP الخاصة بهم.

هل يحتاج MCP stdio ShellGuard إلى مفتاح API؟

لا يذكر إدراجه في السجل أي مفتاح أو سر إلزامي. قد تتطلب بعض الميزات حسابًا لدى الخدمة التي يتصل بها.

هل MCP stdio ShellGuard مفتوح المصدر؟

نعم. شيفرته متاحة على GitHub بترخيص MIT.

من يصون MCP stdio ShellGuard؟

ينشره studiomeyer-io. يدرجه AI.tn لكنه لا يصونه ولا يوصي به.

من سجل MCP الرسمي. الإدراج ليس توصية: راجع شيفرة الخادم وصلاحياته قبل منحه الوصول إلى بياناتك.