अपडेट पर वापस जाएँ
New releaseAug 21, 2026

mcp-stdio-shellguard v0.1.2

MCP stdio सर्वरों के लिए गहन सुरक्षा बंडल: ड्रॉप-इन guardExec/guardSpawn रैपर, AST ऑडिट CLI, संदर्भ MCP सर्वर। Ox-Security 200k-server stdio-RCE श्रेणी (LiteLLM CVE-2025-69256) को समाप्त करता है। MIT, TypeScript, Node >= 20।

साझा करें

StudioMeyer MCP Stack का हिस्सा — Mallorca 🌴 में निर्मित · ⭐ अगर आप इसका उपयोग करते हैं

mcp-stdio-shellguard

npm version npm downloads License Last commit GitHub stars

MCP stdio सर्वर के लिए defense-in-depth बंडल। `child_process.exec/spawn` को allowlist + sandbox + replay-detection के साथ रैप करता है, साथ ही एक AST ऑडिट CLI (`mcp-shellguard-audit`) प्रदान करता है जो MCP सर्वर स्रोतों में असैनिटाइज़्ड शेल कॉल्स को स्कैन करता है। यह Ox-Security MCP stdio-RCE श्रेणी (200k कमज़ोर सर्वर, मई 2026 प्रकटीकरण) को बंद करता है।
  • 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

या सीधे इंस्टॉल किए बिना ऑडिट CLI चलाएँ:

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

यह आपको क्या देता है

तीन परतें, चरणबद्ध रूप से opt-in:

  1. लाइब्रेरी API — drop-in guardExec / guardSpawn जिन्हें आप अपने स्वयं के MCP सर्वर से कॉल करते हैं। डिफ़ॉल्ट-अस्वीकार allowlist, सैंडबॉक्स प्रोफ़ाइल, रीप्ले विंडो।
  2. ऑडिट CLI — mcp-shellguard-audit scan <path> AST को ट्रैवर्स करता है, 12 एंटी-पैटर्न की रिपोर्ट करता है, LOW (no timeout) से लेकर CRITICAL (exec(\...${userInput}...`)`) तक।
  3. संदर्भ MCP सर्वर — mcp-stdio-shellguard-demo 8 टूल्स को उजागर करता है ताकि MCP Inspector / Claude Desktop बंडल को सीधे चला सकें।

टूल्स (संदर्भ सर्वर)

टूलप्रकारउद्देश्य
guard_execविनाशकारीसुरक्षित child_process.exec। args[] वेक्टर, allowlist + सैंडबॉक्स + रीप्ले को बाध्य करता है। stdout, stderr, exitCode, canonicalHash, isReplay, trustTier लौटाता है।
guard_spawnविनाशकारीसुरक्षित child_process.spawn। पूर्ण बॉडी के बजाय stdout/stderr के SHA-256 हैश लौटाता है। shell:true को सख्ती से अस्वीकार करता है।
register_allowlistपरिवर्तनकारीएक टूल नाम को executable + args regex के साथ पंजीकृत करें। पंजीकरण के बिना डिफ़ॉल्ट-अस्वीकार लागू होता है।
audit_sourceकेवल-पठनशेल-इंजेक्शन एंटी-पैटर्न के लिए TS/JS पथ को स्कैन करें। AuditFinding[] + सारांश लौटाता है।
audit_reportकेवल-पठनऑडिट परिणाम को markdown / json / SARIF 2.1.0 के रूप में फ़ॉर्मेट करें।
replay_checkकेवल-पठनकिसी इनवोकेशन के लिए कैनोनिकल SHA-256 हैश की गणना करें और रिपोर्ट करें कि यह पहले से रीप्ले विंडो में है या नहीं।
sandbox_statusकेवल-पठनसक्रिय सैंडबॉक्स प्रोफ़ाइल + ठोस सीमाएँ + cgroup-v2 सक्रिय फ़्लैग की रिपोर्ट करें।
trust_tierकेवल-पठनकिसी पंजीकृत टूल के लिए LOW/MEDIUM/HIGH/CRITICAL टियर और सुधार संकेत प्राप्त करें।

सैंडबॉक्स प्रोफ़ाइल

प्रोफ़ाइलटाइमआउटअधिकतम stdoutअधिकतम stderrFD बजटcgroup-v2
strict5 s1 MB256 KB32हाँ (cpu/memory)
standard (डिफ़ॉल्ट)30 s10 MB1 MB256हाँ
permissive5 min100 MB10 MB1024नहीं

कॉलर प्रति कॉल timeoutMs / fdBudget के माध्यम से कड़ा कर सकता है। कॉलर प्रोफ़ाइल से आगे नहीं बढ़ा सकता।

ट्रस्ट टियर

टियरशर्त
LOWटूल पंजीकृत नहीं (डिफ़ॉल्ट-अस्वीकार)
MEDIUMपंजीकृत लेकिन argsPatterns खाली (कोई भी args अनुमत)
HIGHargsPatterns सेट लेकिन सैंडबॉक्स या रीप्ले ट्रैकर निष्क्रिय
CRITICALargsPatterns + सैंडबॉक्स + रीप्ले सभी सक्रिय

टूल को पंजीकृत करके + argsPatterns सेट करके + guardExec/guardSpawn के माध्यम से चलाकर (जो हमेशा सैंडबॉक्स + रीप्ले सक्रिय करते हैं) LOW → CRITICAL तक बढ़ाएँ।

लाइब्रेरी क्विकस्टार्ट

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

ऑडिट 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

एक्ज़िट कोड:

  • 0 साफ़ (फ़्लोर पर या उससे ऊपर कोई निष्कर्ष नहीं)
  • 1 निष्कर्ष मौजूद
  • 2 पार्स / IO त्रुटियाँ

scanPath या audit_source MCP टूल को पास किए गए कस्टम ignoreGlobs अधिकतम 128 स्ट्रिंग्स स्वीकार करते हैं। प्रत्येक स्ट्रिंग 1024 UTF-16 कोड यूनिट और 16 अनएस्केप्ड ओपनिंग ग्रुपिंग कैरेक्टर्स ((, {, [) तक सीमित है। इन बजट से अधिक इनपुट मैचिंग से पहले एक नियंत्रित त्रुटि उत्पन्न करते हैं।

एंटी-पैटर्न लाइब्रेरी (12 नियम)

IDगंभीरताकब सक्रिय होता है
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_bufferLOWmaxBuffer के बिना exec
missing_timeoutLOWtimeout के बिना exec/spawn

स्कैनर मैचिंग से पहले पुनर्नामित child_process बाइंडिंग्स को हल करता है, इसलिए नीचे दिए गए खतरनाक आकार तब भी पकड़े जाते हैं जब कॉल किसी लिटरल 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(...)

सिंक्रोनस वेरिएंट्स (spawnSync, execFileSync) अपने async नियम साझा करते हैं, और shell_true_option एक स्ट्रिंग शेल ({ shell: "/bin/sh" }) या किसी डायनामिक शेल मान पर भी सक्रिय होता है — केवल लिटरल { shell: true } पर नहीं। किसी गैर-child_process फ़ंक्शन का promisify, किसी अन्य मॉड्यूल से डीस्ट्रक्चर, और { shell: false } साफ़ रहते हैं (कोई गलत पॉज़िटिव नहीं)।

प्रैग्माज़

  • // shellguard:ignore-next-line — एक निष्कर्ष को दबाएँ
  • // shellguard:ignore-file — पूरी फ़ाइल को दबाएँ (दुर्लभ; प्रति-पंक्ति को प्राथमिकता दें)

यह क्यों मौजूद है

श्रेणियाँ