JWT Embedded URL SSRF: When Claims Fetch for You
Sometimes the SSRF parameter is not a form field. It is inside a token the server already trusts. A JWT claim points at a URL; a middleware fetches it to enrich the profile, download a JWKS, pull an avatar, or verify a remote policy document.
You forge or influence that claim, then the server dials your target with its privileged network view.
Where URLs hide in tokens
Scan custom claims first: avatar, picture, callback, webhook, profile, iss when dynamically followed, jwks_uri mirrors, and vendor-specific fields like x5u. OIDC iss discovery is a frequent offender: the API takes an issuer string from the token and fetches /.well-known/openid-configuration without an allowlist.
Test path:
- Obtain a legitimate token for your account.
- Identify any server behavior that implies an outbound HTTP call after authentication—slow requests, SSRF canaries in claims, or logs.
- If you can mint tokens (weak signing key,
alg: none, kid injection, or a second bug), set a claim tohttps://canary.example/ssrf. - If you cannot mint, look for flows that let you register the URL before it is copied into a signed assertion—user settings that end up in a service-to-service JWT.
Blind canaries still count. DNS and HTTP interactions from the cloud egress IP are enough when the response is not reflected.
JWKS and x5u deserve their own paragraph
A token header with jku or x5u pointing at attacker-controlled JSON is classic key confusion. Related pattern: the app ignores jku but reads a JWKS URL from a claim or from iss discovery. Same impact family—SSRF plus potential signature bypass if the fetched keys are trusted.
Keep the report honest. If you only got SSRF to an allowlisted host pattern, say so. If you fetched cloud metadata through the claim, that is critical and needs a careful, non-destructive proof.
Watch multi-tenant products carefully. A tenant admin may be allowed to set an issuer URL that the platform later fetches while validating end-user tokens. That is still SSRF—just gated behind a lower privilege than anonymous access. State the required role clearly so severity lands correctly.
Middleware order surprises
I have seen APIs validate signatures first, then fetch a profile URL from a claim, then authorize. The fetch happens on every request. That raises both reliability risk and SSRF volume. Other stacks fetch once and cache by iss; poisoning that cache is a different writeup, but worth probing with a unique canary path.
Unsigned or weakly signed internal JWTs between microservices are especially juicy. The edge trusts the mesh network and skips verification; a claim URL still gets fetched. Ask whether your in-scope target includes those internal tokens or only browser-facing cookies.
Remediation that matches the bug
Do not fetch URLs from attacker-influenced tokens. Pin trusted issuers and JWKS locations in config. Strip jku/x5u unless you have a closed allowlist. Treat picture claims as opaque strings for the browser, not as server-side fetch targets.
I've watched teams "fix" this by blocking link-local addresses while still allowing the claim to hit their own metadata-adjacent services. Allowlists beat blocklists here.