ZeroHour

CVE-2026-59176

niche

RCE in functype-mcp-server via unsanitized pnpm package-alias install

CVSS 3.1
7.8 high
EPSS
Published
()
Modified
AI analysis

The `set_functype_version` tool in the npm package functype-mcp-server accepts an unvalidated `version` string, interpolates it into the npm specifier `functype@<version>`, and passes it to `pnpm add`, so alias syntaxes such as 'file:' or 'npm:' let the caller install an arbitrary local or remote package under the `functype` name. Any attacker who can get a 'tools/call' request to this MCP tool can trigger it; the tool is registered by default and requires no authentication in stdio mode. Immediately after installation the server calls initDocsData(true), which dynamically imports functype/cli from the newly installed package, executing attacker-controlled module-level JavaScript in the MCP server process and yielding full RCE with that process's privileges (CVSS 3.1 7.8 High, high confidentiality/integrity/availability). Only developers or teams running functype-mcp-server with an MCP client are affected; the vulnerable code is in packages/mcp-server/src/index.ts and maps to CWE-829 (inclusion of functionality from an untrusted control sphere). No public proof-of-concept or in-the-wild exploitation is known, and the issue is not listed in CISA's KEV catalog.

What to do: Until a patched release is identified (none is specified in the current data), restrict or disable the set_functype_version tool in MCP client configurations, and validate the version parameter against a strict semver/dist-tag allowlist before it reaches pnpm add. Audit affected machines by checking whether the functype entry in the project's node_modules resolves to an unexpected local path or unrelated package, and review logs for pnpm add invocations originating from MCP tool calls. Monitor the functype-mcp-server npm feed and repository for a fixed version and upgrade as soon as one is published.

Affected
functype (open-source npm project) functype-mcp-server (npm)
Estimated exposure
nichelikely hundreds to low thousands of developer installations; no published install counts — No download or install counts were provided, so the estimate is based on deployment pattern: this is an opt-in MCP server installed per developer workstation by users of the niche functype npm library, a population plausibly below the…

Order-of-magnitude estimate by the model from install counts, market share and public scan data it knows; verify before quoting.

Description

functype-mcp-server: MCP `set_functype_version` Package Alias RCE via Unsanitized pnpm install + Dynamic Import ## MCP `set_functype_version` Package Alias RCE via Unsanitized pnpm install + Dynamic Import ### Summary The `set_functype_version` MCP tool in `functype-mcp-server` accepts an unconstrained `version` string, interpolates it directly into an npm package specifier (`functype@<version>`), and installs it via `pnpm add` without any validation. Because npm/pnpm package specifiers support `file:`, `npm:`, and other alias syntaxes, an attacker who can send an MCP `tools/call` request to this tool can cause the server to install an arbitrary local or remote package as `functype`. Immediately after installation, the server calls `initDocsData(true)`, which dynamically imports `functype/cli` from the newly installed location, executing attacker-controlled JavaScript in the MCP server process. This results in full Remote Code Execution (RCE) with the privileges of the server process — full confidentiality, integrity, and availability impact (CVSS 7.8 High). ### Details The vulnerable code is in `packages/mcp-server/src/index.ts`. The `set_functype_version` tool is registered at line 115 and is enabled by default (no authentication required in stdio mode). **Source (user input accepted without validation):** ```ts // packages/mcp-server/src/index.ts:119-121 parameters: z.object({ version: z.string().describe('The functype version to install (e.g., "0.46.0", "latest", "^0.45.0")'), }), ``` Only `z.string()` validation is applied — no semver format check, no allowlist for dist-tags, and no rejection of `file:`, `npm:`, URL, or path alias syntaxes. **Sink 1 — arbitrary package installation:** ```ts // packages/mcp-server/src/index.ts:122-125 execute: async (args) => { const spec = `functype@${args.version}` try { execFileSync("pnpm", ["add", spec], { cwd: PROJECT_ROOT, stdio: "pipe", timeout: 60_000 }) ``` `args.version` is interpolated into the package specifier string and passed directly to `pnpm add`. Supplying `file:/path/to/evil` causes pnpm to install an attacker-controlled directory as the `functype` package alias. **Sink 2 — dynamic import executes installed package code:** ```ts // packages/mcp-server/src/lib/docs/data.ts:23-30 if (force) { const resolvedPath = require.resolve("functype/cli") cli = await import(`${pathToFileURL(resolvedPath).href}?t=${Date.now()}`) } ``` `initDocsData(true)` is called immediately after installation (line 134 in `index.ts`). It resolves `functype/cli` from the node_modules that now points to the attacker's package and dynamically imports it, executing any module-level code in the attacker's `cli.js` at import time. **Data flow summary:** 1. `index.ts:115` — MCP tool `set_functype_version` registered, no auth required. 2. `index.ts:119-121` — `version` accepted as raw `z.string()` (source). 3. `index.ts:123` — `functype@${args.version}` constructed without sanitization. 4. `index.ts:125` — `execFileSync("pnpm", ["add", spec], ...)` installs attacker-controlled package (sink: arbitrary install). 5. `index.ts:134` — `initDocsData(true)` called immediately. 6. `data.ts:29-30` — `require.resolve("functype/cli")` + dynamic `import()` executes attacker module (sink: RCE). ### PoC **Step 1 — Prepare the attacker-controlled evil package:** ```bash mkdir -p /tmp/evil cat > /tmp/evil/package.json <<'EOF' {"name":"evil-functype","version":"1.0.0","type":"module","exports":{"./cli":"./cli.js"}} EOF cat > /tmp/evil/cli.js <<'EOF' import { writeFileSync } from "node:fs"; writeFileSync("/pwned.txt", "RCE: mcp import-time code execution via set_functype_version\n"); export const TYPES = {}; export const INTERFACES = {}; export const CATEGORIES = {}; export const FULL_INTERFACES = {}; export const VERSION = "1.0.0"; EOF ``` **Step 2 — Clone and build the victim monorepo at the affected version:** ```bash TMP="$(mktemp -d)" git clone https://github.com/jordanburke/functype.git "$TM

Ecosystems
npm
Weakness
CWE-829
Vector
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
GHSA
GHSA-wcjj-9m6g-2fr2 (high)

In the news

No ingested article mentions this CVE yet.