DEV Community

jeffrey
jeffrey

Posted on

When the model supplies the parameter: CVE-2026-54547 and CVE-2026-54549 in the Meta Ads MCP server

When the model supplies the parameter: CVE-2026-54547 and CVE-2026-54549 in the Meta Ads MCP server

Two advisories affect the Meta Ads MCP server, scored 7.4 each. One concerns a URL parameter that the server fetches. The other concerns an authorization check that reads the wrong header. Together they show how a tool argument becomes a network request and how a middleware bug becomes an open door.

CVE-2026-54549: a URL parameter fetched without validation

The upload_ad_image tool accepts a parameter named image_url. The server fetches that URL with follow_redirects=True and performs no validation of the scheme, the host or the IP address.
The consequence is server-side request forgery available through a tool argument. A caller who can influence the parameter chooses where the server connects. The absence of scheme validation means a scheme other than HTTP may be attempted. The absence of host and IP validation means an internal address is as acceptable as an external one. The redirect flag means a permitted first hop can lead to a blocked destination, because the check that would have refused the destination never runs.
The important detail is the position of the parameter. A model supplies tool arguments, so the value is attacker-influenced even when the caller is otherwise legitimate. The server treated it as configuration.

CVE-2026-54547: the header the middleware did not read

The second issue is in the authorization middleware. The advisory states that the middleware rejects a request only when both tokens are absent, and that it ignores the primary X-Pipeboard-Token header.
The logic admits two failures. A request that omits the token the middleware actually reads proceeds, because the middleware only fails a request where both are missing. And a component that sets the primary header, believing it is the credential the server checks, is writing to a value the middleware does not read.
Both are the same mistake seen from different sides: the authorization decision and the credential presentation disagree about which field matters.

What the pair illustrates

The two advisories sit at opposite ends of the same request. CVE-2026-54549 concerns what the server does with a value it received. CVE-2026-54547 concerns whether the server should have received the request at all.
For anyone building or reviewing an MCP integration, the pair produces a short checklist. Any tool parameter that becomes a URL, a path, a header or a command line is untrusted input, and the validation for it is the validation for an external request. And any middleware that reads a credential should read the field the clients actually set, which is confirmed by testing a request with the credential present in the expected place.

Remediation

Upgrade to the fixed versions named in the advisories. The server-side validation for the URL parameter should reject schemes other than HTTP and HTTPS, resolve the host and refuse private address ranges, and either disable redirect following or re-validate the destination after each hop.
On the middleware side, the fix is to require the token rather than to require that not all tokens are missing, and to align the header the server reads with the header the clients set. A test that sends a request with a valid token and no token, and asserts the two outcomes differ, catches this class before deployment.
Network policy completes the picture. An outbound rule that limits which hosts the server can reach reduces the value of any future fetch parameter, regardless of how well the validator is written.

References

Top comments (1)

Collapse
 
autenai profile image
Auten •

Two additions to the SSRF checklist, because "validate the URL" is where most fixes stop:

  • Validate the address you actually connect to, not the hostname you checked. If you resolve the host, check the IP, then hand the hostname to the HTTP client, it resolves again, and a DNS-rebinding host can answer public the first time and 169.254.169.254 the second. Resolve once, check that IP, connect to that IP (with the Host header / SNI set). Same rule for every redirect hop if you keep redirects on.
  • Remember the IPv6 and odd encodings of private ranges: ::ffff:127.0.0.1, [::1], 0.0.0.0, decimal or octal forms like 2130706433. A string-prefix blocklist misses most of them; parse to an IP object and test ranges.

Your framing generalizes past URLs, and it bites hardest in MCP servers that act on a real screen, which is what we work on at Auten. There the model's arguments are partly derived from text it just read off the screen, so a web page or an email body is an injection channel into the next tool call. The pattern that held up for us is the same as yours: don't let the model choose where a sensitive value goes. Saved logins are pinned to the site or app they were first used on; on any other origin the server refuses and types nothing, and only the user can re-pin. The model can ask to fill a login, but it can't redirect the credential, so a lookalike page in the middle of a run gets nothing.