registry  /  mcp-proxy  /  6.5.3

mcp-proxy@6.5.3

A TypeScript SSE proxy for MCP servers that use stdio transport.

AI Security Review

scanned 2h ago · by lpm-firewall-ai

No confirmed malicious attack surface. The CLI intentionally proxies a user-selected local MCP server and can optionally expose its local HTTP listener through a user-requested tunnel.

Static reason
One or more suspicious static signals were detected.
Trigger
User runs `mcp-proxy` with a command; `--shell` and `--tunnel` are explicit opt-ins.
Impact
The selected child process inherits the caller environment; enabling a tunnel intentionally exposes the proxy endpoint.
Mechanism
User-invoked stdio-to-HTTP proxy with optional public tunneling.
Rationale
Static inspection shows expected proxy behavior, not autonomous or install-time attack activity. Scanner signals map to intentional CLI process spawning, optional tunneling, TLS file reads, and bundled yargs code.
Evidence
package.jsonsrc/bin/mcp-proxy.tssrc/StdioClientTransport.tssrc/startHTTPServer.tsdist/bin/mcp-proxy.mjs
Network endpoints1
tunnel.gla.ma

Decision evidence

public snapshot
AI called this Clean at 96.0% confidence as Benign with low false-positive risk.
Evidence for block
  • `src/bin/mcp-proxy.ts` forwards the user-supplied command, arguments, and environment to a child process.
  • `src/StdioClientTransport.ts` uses `spawn`; shell execution is disabled unless the user explicitly passes `--shell`.
  • `src/bin/mcp-proxy.ts` optionally opens a public tunnel only when `--tunnel` is supplied.
Evidence against
  • `package.json` has no preinstall, install, postinstall, or other lifecycle hook.
  • No source writes agent configuration, shell profiles, persistence files, or arbitrary package files.
  • `src/startHTTPServer.ts` only reads user-specified TLS CA/certificate/key paths.
  • Bundled profile-write strings are dormant yargs localization/completion dependency code, not invoked by package source.
  • No credential harvesting, exfiltration logic, remote payload loading, eval, or VM execution found.
Behavioral surface
Source
ChildProcessCryptoDynamicRequireEnvironmentVarsEvalFilesystemNetworkShell
Supply chain
HighEntropyStringsUrlStrings
ManifestNo manifest risk signals triggered.
scanned 24 file(s), 1.33 MB of source, external domains: 127.0.0.1, admin.example.com, api.example.com, app.example.com, datatracker.ietf.org, example.com, github.com, json-schema.org, malicious.com, raw.githubusercontent.com, stackoverflow.com, subdomain.example.com, tunnel.gla.ma, yargs.js.org

Source & flagged code

5 flagged · loading source
dist/bin/mcp-proxy.mjsView file
12import { readFileSync as readFileSync$1, readdirSync as readdirSync$1 } from "node:fs"; L13: import { spawn } from "node:child_process"; L14: import { PassThrough, Transform } from "node:stream";
High
Child Process

Package source references child process execution.

dist/bin/mcp-proxy.mjsView on unpkg · L12
12Cross-file remote execution chain: dist/bin/mcp-proxy.mjs spawns dist/stdio-DNR9B0BZ.mjs; helper contains network access plus dynamic code execution. L12: import { readFileSync as readFileSync$1, readdirSync as readdirSync$1 } from "node:fs"; L13: import { spawn } from "node:child_process"; L14: import { PassThrough, Transform } from "node:stream"; ... L81: event: eventType || void 0, L82: data: data.endsWith(` L83: `) ? data.slice(0, -1) : data ... L175: throw TypeError(msg); L176: }, __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg), __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private fie... L177: var EventSource = class extends EventTarget { ... L202: } L203: const decoder = new TextDecoder(), reader = body.getReader(); L204: let open = !0;
High
Cross File Remote Execution Context

Source spawns a local helper that also contains network and dynamic execution context; review data flow before blocking.

dist/bin/mcp-proxy.mjsView on unpkg · L12
1445} L1446: } else config = mixin.require(resolvedConfigPath); L1447: setConfigObject(config);
Medium
Dynamic Require

Package source references dynamic require/import behavior.

dist/bin/mcp-proxy.mjsView on unpkg · L1445
12import { readFileSync as readFileSync$1, readdirSync as readdirSync$1 } from "node:fs"; L13: import { spawn } from "node:child_process"; L14: import { PassThrough, Transform } from "node:stream"; ... L81: event: eventType || void 0, L82: data: data.endsWith(` L83: `) ? data.slice(0, -1) : data ... L175: throw TypeError(msg); L176: }, __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg), __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private fie... L177: var EventSource = class extends EventTarget { ... L202: } L203: const decoder = new TextDecoder(), reader = body.getReader(); L204: let open = !0;
Medium
Install Persistence

Source writes installer persistence such as shell profile or service configuration.

dist/bin/mcp-proxy.mjsView on unpkg · L12
dist/stdio-DNR9B0BZ.mjsView file
294try { L295: new Function(""); L296: return true;
Low
Eval

Package source references a known benign dynamic code generation pattern.

dist/stdio-DNR9B0BZ.mjsView on unpkg · L294

Findings

3 High4 Medium5 Low
HighChild Processdist/bin/mcp-proxy.mjs
HighShell
HighCross File Remote Execution Contextdist/bin/mcp-proxy.mjs
MediumDynamic Requiredist/bin/mcp-proxy.mjs
MediumNetwork
MediumEnvironment Vars
MediumInstall Persistencedist/bin/mcp-proxy.mjs
LowScripts Present
LowEvaldist/stdio-DNR9B0BZ.mjs
LowFilesystem
LowHigh Entropy Strings
LowUrl Strings