Back to skill

Security audit

graph-polymarket-mcp

Security checks for vulnerabilities and agentic risk

Overview

This is a real Polymarket data MCP server, but its optional HTTP/SSE mode can expose unauthenticated credential-backed tools to the network.

Install only if you need Polymarket/The Graph data access and are comfortable providing a Graph API key. Prefer stdio/local use. Do not expose --http or --http-only to a network unless you add authentication, bind or firewall it to trusted clients, and accept that callers can spend your Graph API quota. Pin the npm package version when installing or configuring clients.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Error
Location
src/index.ts:1791
Finding

Unauthenticated MCP HTTP/SSE Service Binds to All Network Interfaces

Content
View full analysis

Vulnerability Details

File Location: src/index.ts:1791-1819
Vulnerability Type: Unauthenticated externally reachable MCP service
Risk Level: High when HTTP/SSE mode is enabled

Vulnerable Code

ts
function startHttpTransport(port: number) {
  const app = express();
  const sessions = new Map<string, SSEServerTransport>();

  app.get("/sse", async (req, res) => {
    const transport = new SSEServerTransport("/messages", res);
    sessions.set(transport.sessionId, transport);
    res.on("close", () => {
      sessions.delete(transport.sessionId);
    });
    await server.connect(transport);
  });

  app.post("/messages", async (req, res) => {
    const sessionId = req.query.sessionId as string;
    const transport = sessions.get(sessionId);
    if (!transport) {
      res.status(400).json({ error: "Invalid or expired session" });
      return;
    }
    await transport.handlePostMessage(req, res);
  });

  app.get("/health", (_req, res) => {
    res.json({ status: "ok", server: "graph-polymarket-mcp" });
  });

  app.listen(port, () => {
    console.error(`SSE transport listening on http://localhost:${port}/sse`);
  });
}

Technical Analysis

The HTTP/SSE transport does not authenticate or authorize requests to /sse or /messages. Any client that can reach the listener can create an MCP session and invoke the registered tools.

Additionally, app.listen(port) does not explicitly restrict the listener to loopback. In a typical Node.js deployment, this listens on an unspecified address covering all available network interfaces. The log message claims that the endpoint is available at localhost, but this does not enforce localhost-only access.

This becomes exploitable when HTTP mode is enabled through --http, --http-only, or MCP_HTTP_PORT. The exposed tools include custom GraphQL querying through the operator's GRAPH_API_KEY. ...[truncated 1821 chars]

Remediation
View remediation

Remediation Suggestions

  1. Bind to loopback explicitly by default:

    ts
    app.listen(port, "127.0.0.1", () => {
      console.error(`SSE transport listening on http://127.0.0.1:${port}/sse`);
    });
    
  2. Require a separate, explicit configuration option before allowing a non-loopback bind address. Display a prominent warning when external binding is selected.

  3. Protect both /sse and /messages with authentication, such as a high-entropy bearer token or authentication enforced by a trusted reverse proxy.

  4. Apply authorization consistently to session creation and message submission. Do not treat possession of a session identifier as sufficient authorization.

  5. Validate Origin and Host headers against an operator-configured allowlist to reduce browser-based and DNS-rebinding attack exposure.

  6. Add per-client rate limits, maximum concurrent-session limits, idle session expiration, request-size limits, and upstream query budgets.

  7. When remote access is required, terminate TLS at a trusted reverse proxy and restrict access using firewall rules or a private network.

  8. Update the startup log to report the actual bind address rather than always claiming that the service is on localhost.

  9. Add automated tests verifying that default HTTP mode is reachable only through loopback and that unauthenticated requests are rejected when authentication is configured.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (24)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The documented behavior significantly overstates the implemented functionality, claiming subgraph access, analytics, P&L, open interest, resolution, and attribution that static analysis says are not actually present. This can mislead operators into exposing credentials, trusting outputs, or making decisions based on nonexistent controls or capabilities, which is a security-relevant integrity issue.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: fast-uri==3.1.5 — 4 advisory(ies): CVE-2026-75931 (fast-uri vulnerable to host confusion via skipped IDN canonicalization on scheme); CVE-2026-75975 (fast-uri vulnerable to server-side request forgery via malformed IPv6 normalizat); CVE-2026-75899 (fast-uri vulnerable to server-side request forgery via repeated hostname percent) +1 more

High
Category
Supply Chain
Confidence
88% confidence
Finding

The lockfile pins fast-uri 3.1.5, and the cited advisories describe URI parsing/canonicalization flaws that can enable SSRF or host confusion when the library is used for trust decisions on attacker-controlled URLs. In this skill’s context, the package is transitive via ajv rather than directly used by the application, so exploitability depends on whether untrusted schemas/URIs are processed; that makes the issue real but context-limited.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding

The README instructs users to run the MCP server via npx graph-polymarket-mcp without pinning an exact package version. That allows future package updates, account compromise, or a malicious republish to change the code executed at install/run time, creating a supply-chain risk for users who follow the documentation.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
96% confidence
Finding

The Claude Desktop configuration example uses npx -y graph-polymarket-mcp without a pinned version, so clients may fetch and execute whatever package version is current at the time of use. In an MCP context this is especially sensitive because the launched server receives tool invocation access and environment variables such as GRAPH_API_KEY.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding

The Claude Code setup command references the package without version pinning, which exposes users to unintended code changes or malicious package updates when the command is later re-run or copied by others. Because this is an MCP server, a compromised package could abuse agent trust boundaries or exfiltrate configured secrets.

Content

No source excerpt is available for this finding.

Unrestricted Tool Access

Medium
Category
Excessive Agency
Confidence
80% confidence
Finding

Skill grants unrestricted tool access without appropriate constraints. An agent with unfettered tool access can perform arbitrary actions including file modification, network requests, and code execution.

Content

Scanner excerpt · README.md (reported line 78)May include surrounding context.

md
### OpenClaw / Remote Agents (SSE)

> **The SSE transport has no authentication.** Anyone who can reach the port can call every tool,
> and those calls spend *your* `GRAPH_API_KEY` quota. `--http` binds `0.0.0.0` inside a container,
> so publish it to `127.0.0.1` on the host and put a reverse proxy with TLS and auth in front of
> anything reachable off-box. For local agents, prefer the default stdio transport — it has no

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding

The documented HTTP launch command uses npx graph-polymarket-mcp --http without an exact version. This creates a supply-chain execution risk and is more concerning here because the HTTP mode exposes a network service and uses the user's GRAPH_API_KEY, increasing the value of compromising the launched package.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding

The SSE-only deployment example launches an unpinned package version, meaning the executable code may change over time or be replaced through package compromise. In a remote deployment scenario this can amplify risk because the process may run continuously and expose a callable service to other systems.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding

The custom-port example still executes the package through unpinned npx, preserving the same supply-chain risk as the other command variants. If the package were hijacked, an operator following this README could start attacker-controlled code with access to local environment variables and network connectivity.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding

The transport modes table includes npx graph-polymarket-mcp invocations without version pinning, reinforcing unsafe copy-paste guidance throughout the README. Repetition in documentation increases the chance that users deploy mutable package references in production or agent environments.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
86% confidence
Finding

The skill declares concrete environment and network capabilities in metadata but does not define an explicit tool scope such as permissions or allowed-tools. That weakens least-privilege enforcement and makes it easier for a host or operator to grant broader access than intended, especially since the skill can consume a credential and make outbound requests.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
92% confidence
Finding

Using npx graph-polymarket-mcp without a pinned version allows the latest published package to be fetched at install/run time, creating a supply-chain risk. If the package is compromised or a breaking/malicious version is published, users may execute unreviewed code that has network access and can use GRAPH_API_KEY.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · package.json (reported line 12)May include surrounding context.

json
},
  "main": "./build/index.js",
  "scripts": {
    "build": "tsc && chmod 755 build/index.js",
    "start": "node build/index.js",
    "start:http": "node build/index.js --http",
    "start:http-only": "node build/index.js --http-only",

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
99% confidence
Finding

The manifest description at L004 says the skill provides 35 tools, but the documentation at L078 states '20 tools available.' This is an active contradiction in the skill's own documentation about the scope of functionality exposed.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: hono==4.13.1 — 3 advisory(ies): CVE-2026-84363 (Hono: Query parser reads parameters after the URL fragment, causing cache-key an); CVE-2026-84364 (Hono: Unbounded dot-notation nesting in `parseBody()` can cause memory exhaustio); CVE-2026-84365 (Hono: Incomplete fix for CVE-2026-39408: `toSSG()` still writes files outside th)

Low
Category
Supply Chain
Confidence
74% confidence
Finding

The lockfile includes hono 4.13.1 through the MCP SDK, and the referenced advisories indicate real upstream flaws involving query parsing, parseBody() resource exhaustion, and path traversal in toSSG(). For this skill, Hono appears to be a transitive server dependency rather than an explicitly exposed framework feature, so the path traversal issue is likely not reachable, but query/body parsing issues could matter if the SDK exposes HTTP endpoints to untrusted clients.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: qs==6.15.3 — 2 advisory(ies): CVE-2026-82417 (qs: Denial of Service via Attacker Controlled isBuffer); CVE-2026-82562 (qs array-limit bypass via bracket-key comma parsing)

Low
Category
Supply Chain
Confidence
82% confidence
Finding

qs 6.15.3 is present in the lockfile and the reported advisories describe denial-of-service and parser limit-bypass behavior on attacker-controlled query strings or form data. In this package, qs is used by Express-related components, so the vulnerability is genuine, but impact is mostly availability-related and depends on whether the skill accepts untrusted HTTP requests with complex query/body payloads.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 46)May include surrounding context.

json
"url": "https://github.com/PaulieB14/graph-polymarket-mcp/issues"
  },
  "dependencies": {
    "@modelcontextprotocol/sdk": "^1.30.0",
    "express": "^4.21.0",
    "zod": "^3.24.0"
  },

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 47)May include surrounding context.

json
},
  "dependencies": {
    "@modelcontextprotocol/sdk": "^1.30.0",
    "express": "^4.21.0",
    "zod": "^3.24.0"
  },
  "devDependencies": {

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 48)May include surrounding context.

json
"dependencies": {
    "@modelcontextprotocol/sdk": "^1.30.0",
    "express": "^4.21.0",
    "zod": "^3.24.0"
  },
  "devDependencies": {
    "@types/express": "^5.0.0",

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 51)May include surrounding context.

json
"zod": "^3.24.0"
  },
  "devDependencies": {
    "@types/express": "^5.0.0",
    "@types/node": "^22.0.0",
    "typescript": "^5.7.0"
  },

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 52)May include surrounding context.

json
},
  "devDependencies": {
    "@types/express": "^5.0.0",
    "@types/node": "^22.0.0",
    "typescript": "^5.7.0"
  },
  "engines": {

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 53)May include surrounding context.

json
"devDependencies": {
    "@types/express": "^5.0.0",
    "@types/node": "^22.0.0",
    "typescript": "^5.7.0"
  },
  "engines": {
    "node": ">=18.0.0"

Vague Triggers

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

This manifest says the GRAPH_API_KEY is "optional" in the description but marks it as required with "isRequired": true. In a manifest file, contradictory setup conditions reduce specificity about when the skill can be used successfully and can lead to unintended or confusing invocation behavior.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The manifest describes a 35-tool Polymarket data skill, but this file also registers multiple MCP prompts and can expose the server over HTTP/SSE in addition to stdio. Those capabilities are not harmful by themselves, but they are additional operational behavior beyond the narrow '35 tools for querying data' description.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.exposed_secret_literal

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
smithery.yaml:16