# FastMCP OAuth Callback Reflected XSS

- **Severity:** High
- **Signature ID:** `7c3f9a2e-5d41-4b8a-9e02-6f1c8d4b7a35`

## Summary

FastMCP versions before 2.13.0 build the OAuth callback page by inserting URL parameters directly into HTML without escaping them. An attacker who gets a victim to open a crafted callback link can run JavaScript in the victim's session, right at the moment OAuth tokens are being exchanged.

## How the attack works

An attacker crafts a link to the FastMCP OAuth callback endpoint with script markup, an event-handler attribute, or a javascript:/data: URL scheme in the query string or body, possibly percent-encoded to dodge basic filters. The victim opens the link, often after fetching it from an attacker-controlled page. FastMCP reflects the unescaped parameter into the generated HTML and the browser executes it. Because this happens during an active OAuth authorize/token exchange, the injected script can intercept or exfiltrate the resulting access/refresh tokens.

## Why it matters

A successful callback injection lets an attacker steal OAuth tokens issued during the exchange, giving them the same access as the victim's authenticated session without needing credentials.

## What you can do

- Upgrade FastMCP to 2.13.0 or later, which escapes callback parameters.
- Audit any custom OAuth callback handlers for unescaped output of query, body, or header values.
- Restrict which redirect/callback URLs your OAuth clients accept, and reject ones containing script markup or javascript:/data: schemes.
- Treat detections from known scanners or developer testing as expected; verify the process lineage before escalating, and investigate anything originating from an unfamiliar browser or agent session.

## Known benign look-alikes

- Authorized security testing — DAST scanners, Burp/ZAP payload replay or a red-team engineer manually probing the FastMCP callback endpoint with alert()/img-onerror payloads. These are true detections of the technique but expected activity; correlate with the reported process lineage (scanner binary vs. browser/agent) before escalating.
- A developer working on oauth_callback.py locally and passing markup through the callback query string to verify the escaping fix. Same signature, benign intent.
- An agent fetching an XSS write-up, CVE advisory or cheat-sheet whose URL happens to contain a "/callback" segment together with a sample payload in the query string.
- An OAuth provider redirecting back with an error_description that contains raw angle brackets or quotes from an upstream error message. Mitigated by requiring tag names, on*= handlers, javascript:/data:text/html schemes or entity-encoded '<' rather than bare punctuation.
- Redirect-chain or URL-shortener traffic where an encoded downstream target string resembles a script scheme. Mitigated by requiring the callback-shaped path on the triggering request itself.

## References

- https://owasp.org/Top10/A03_2021-Injection/
- https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html
- https://github.com/jlowin/fastmcp

---
Source: https://www.netzilo.com/threats/fastmcp-oauth-callback-xss
