GitHub Advisoryadvisory · PyPI

GHSA-45gf-fjxp-cjpq meta-ads-mcp: Server-Side Request Forgery (SSRF) in `upload_ad_image` via Unrestricted `image_url` Fetch

HIGH Published 2026-07-17 Modified 2026-07-17 Official page ↗
Aliases
CVE-2026-54549
Ecosystem
PyPI
Packages
meta-ads-mcp
Severity
High
CVSS vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:L
Weaknesses
CWE-918
Reviewed
2026-07-17

Affected packages

• PyPI meta-ads-mcp: < 1.0.115 → fixed in 1.0.115

Description

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 - GET /poc.jpg | User-Agent: 'curl/8.4.0' ``` Alternative targets Replace `http://127.0.0.1:9009/poc.jpg` with: • `http://169.254.169.254/latest/meta-data/` — cloud instance metadata (AWS/GCP/Azure) • `http://10.0.0.1/` — RFC 1918 internal network services • `http://attacker.com/redirect` — a public URL that redirects to an internal target (exploitable via `follow_redirects=True`) Impact This is a Server-Side Request Forgery (SSRF) vulnerability. Any party capable of sending a JSON-RPC `tools/call` request to the MCP HTTP endpoint—using any non-empty Bearer token string—can instruct the server to make arbitrary outbound HTTP GET requests, including to: • Localhost services: databases, admin panels, internal APIs, and other processes bound to `127.0.0.1` on the host • RFC 1918 / private network addresses: internal microservices, Kubernetes control planes, cloud-internal load balancers • Cloud instance metadata endpoints: `http://169.254.169.254/` (AWS IMDSv1, GCP, Azure), potentially exposing IAM credentials, instance identity documents, and bootstrap secrets • Redirect-chained internal targets: any internal host reachable via a public-to-private redirect, because `follow_redirects=True` is set on all three fetch paths without re-validation at each hop The SSRF fires *before* Meta API credential validation, so no valid Meta OAuth token is required. The impact spans confidentiality (internal data exfiltration), integrity (requests that trigger state-changing actions on internal services), and limited availability (internal service disruption). Operators deploying `meta-ads-mcp` with `--transport streamable-http` in environments co-located with sensitive internal services or cloud metadata services are directly at risk. Reproduction artifacts `Dockerfile` ```dockerfile FROM python:3.11-slim Install system build dependencies RUN apt-get update && \ apt-get install -y --no-install-recommends gcc && \ rm -rf /var/lib/apt/lists/* WORKDIR /app Install pip and uv for fast dependency installatio…

Related

Alias · CVE (1)

  • CVE-2026-54549 Meta Ads MCP is a Model Context Protocol (MCP) server that lets AI assistants run Meta Ads. vulnerability

Weakness · CWE (1)

  • CWE-918 Server-Side Request Forgery weakness

References