← Back to all reports

Unauthenticated Server Request Forgery via NFT Metadata

Reported Feb 21, 2026
Severity High
Platform Web
Vulnerability Class Server-Side Request Forgery (CWE-918)
Target Type Self-Custody Wallet Provider
Impact Unauthenticated outbound requests with content-type oracle

The Risk

The wallet provider's servers could be tricked into making web requests to any address an attacker pointed them at, with no login required. The attacker simply published a fake collectible whose listing told the server to go fetch a file from their own server, and the server obeyed. This is the kind of foothold attackers use to reach private internal systems that are not supposed to be visible from the internet, and to map a company's hidden infrastructure from the outside.

The Vulnerability

An unauthenticated metadata endpoint accepted a contract address and token ID, looked up the corresponding NFT metadata, then performed a server-side request to whatever URL appeared in the metadata's image or animation_url field. The result of that request, specifically the inferred media type, was reflected back to the caller as media.type.

The outbound request had no protections in place:

  • No allowlist for schemes or hosts
  • No filtering of private, loopback, or link-local addresses after DNS resolution
  • No defense against DNS rebinding
  • Redirects were followed cross-host without restriction
  • No authentication required to trigger the request

The Attack

The attacker deploys a minimal NFT contract whose tokenURI() returns metadata pointing at an attacker-controlled URL.

curl -s "https://[redacted-host]/api/v1/metadata/token?contract=<ATTACKER_NFT>&id=1&type=erc721"

The response echoed the attacker-controlled name, description, and media.url fields straight back, and inbound requests from the wallet provider's backend showed up at the attacker's logging endpoint.

Content-Type Oracle

By varying the response from the attacker's server, the inferred media.type reflected by the API flipped between image and video. This proved the backend was making a live server-side request and using the response, turning the endpoint into a semi-blind oracle suitable for service fingerprinting.

Redirect Following

When the attacker server returned a 302 to a different domain with a misleading content-type header, the API's reflected media.type matched the final destination, not the canary. This proved the backend follows cross-host redirects, which extends the SSRF reach beyond what an allowlist on the original URL would catch.

The Impact

  • Any unauthenticated party can coerce the wallet provider's backend into outbound HTTP requests of their choice
  • Internal IP ranges, cloud metadata services, and same-account services may be reachable since no IP filtering was observed
  • The content-type oracle allows the attacker to distinguish reachable services from unreachable ones, enabling internal service mapping
  • Redirect following expands the surface to any target the attacker can stage a redirector for
  • The same code path was shared across multiple chain-specific deployments, multiplying the affected infrastructure

Remediation

  • At the outbound request sink, allow only https: and reject every other scheme.
  • Resolve the destination host and reject private, loopback, link-local, and cloud metadata addresses (IPv4 and IPv6) before issuing the request.
  • Disable redirects, or restrict redirects to the same host that was originally validated. Re-validate the destination after every hop.
  • Enforce tight timeouts, response size caps, and concurrency limits.
  • The simplest fix is to remove the server-side fetch entirely and let clients fetch the media URL directly. The backend can return the URL without inspecting it.