The authorization server validates the redirect_uri against the registered list. The scanner marks the endpoint as compliant. The authorization code just arrived at the attacker's server.
This is not a misconfiguration problem. It is a pre-condition failure with 5 observable variables before any exploitation.
The Redirect Is Not the Exploit. The Code Exchange Is.
Calling this class "open redirect" hides the actual primitive. The sensitive payload is not the redirected user. It is the authorization code delivered to the wrong endpoint.
The OAuth Authorization Code flow has 2 critical steps. In the first, the authorization server sends the code to the request's redirect_uri. In the second, the client exchanges that code for an access token at the token endpoint.
RFC 6749 §4.1.3 is direct: the token endpoint MUST validate that the redirect_uri in the exchange request is identical to the original authorization. When this validation is absent, any captured code can be exchanged by whoever holds it.
Report H1 #665651 in the GSA Bounty program (login.fr.cloud.gov) demonstrates the real outcome. The open redirect delivered the authorization code to the attacker's endpoint. With PKCE absent, the code was exchanged directly for an access token. Bounty: $750, high severity, account takeover demonstrated.
The critical distinction: phishing via open redirect sends the user somewhere else. Authorization code interception sends the cryptographic grant. These are 2 different threat models, with distinct proof-of-concept requirements for triage.
The previous post on redirect_uri and PKCE covers weak validation mechanisms as an access vector. This post covers what determines exploitability after the bypass is confirmed: the 5-condition matrix.
Reports in this class fail triage as low for a simple reason. They document the redirect to the attacker's server, not the code capture. The redirect is the delivery. The code-for-token exchange is the exploit.
Bypass Techniques as Force Multipliers
Each bypass technique exploits a different assumption in the server's validator. The payload must match the specific failure point of each validator.
Path traversal is the most documented vector. The payload https://app.example.com/callback/../attacker fools validators that normalize the path before comparing. The browser resolves the traversal completely. Report H1 #1861974 confirms authorization code capture via this vector. The token endpoint did not revalidate the redirect_uri during the code exchange, delivering the access token to the attacker.
Subdomain wildcard works when the server accepts *.example.com. The attacker registers evil.example.com. Dangling subdomains via deprovisioned cloud resources amplify the vector without requiring direct host control. The validator sees the correct suffix; the attacker controls the host.
Parameter pollution exploits parsers that take the first or last value from duplicate parameters. The payload redirect_uri=https://app.com/callback&redirect_uri=https://attacker.com causes the server to validate one value and the client to send to another.
CVE-2020-26938 exposes a different failure. node-oauth2-server up to version 3.1.1 validates the redirect_uri only against the regex [a-zA-Z][a-zA-Z0-9+.-]+:. URIs with javascript: and data: schemes pass this validation. CVSS 7.2 HIGH. No fixed version is available.
CVE-2024-8883 shows a less obvious vector. Keycloak before 24.0.8 treats localhost in Valid Redirect URIs as permission to redirect externally. The scanner sees "localhost" in the list and marks it as valid. The functional probe exposes the redirect to the outside. CVSS 6.1.
The common thread across all techniques: the bypass does not create the exploit alone. It delivers the code outside the legitimate perimeter. What the attacker can do with that code depends on the other conditions in the matrix.
PKCE: The Condition That Defines Exploitability
Absent PKCE is the decisive multiplier between theoretical and exploitable interception. Without code_verifier enforcement at the token endpoint, any captured code is immediately exchangeable.
The RFC 7636 mechanism works in 2 steps. The client generates a code_verifier of 43 to 128 random characters and calculates code_challenge = BASE64URL(SHA256(verifier)). The token endpoint requires the original verifier to complete the exchange.
With S256, the attacker who captures the code does not have the verifier. They cannot reconstruct it from the challenge. A captured code without the corresponding verifier is useless at the token endpoint.
CVE-2025-4144 demonstrates what happens when enforcement fails in production. Cloudflare's workers-oauth-provider before 0.0.5 processed the code_verifier in handleTokenRequest even without code_challenge in the authorization. Any string passed as a valid verifier. PKCE was fully downgraded to absent. CVSS 5.3. The vector was critical because this provider serves as the base for MCP OAuth 2.1 compatible implementations.
The observable signal is direct. A successful authorization request without the code_challenge parameter confirms PKCE is not enforced. The captured code can be exchanged directly.
Reports H1 #665651 (GSA) and H1 #861940 (Semrush) explicitly cite the absence of PKCE as a confirmed pre-condition. Both reached high severity. Reports that document redirect_uri bypass with active PKCE S256 rarely reach P2, because the captured code cannot be exchanged.
HackerOne: 4 Confirmed Reports of Code Interception
4 public HackerOne reports document real authorization code interception. Each combined a weak redirect_uri with at least one additional condition from the matrix.
H1 #665651 (GSA Bounty, login.fr.cloud.gov): Open redirect on redirect_uri with absent PKCE. High severity, $750. Authorization code captured and exchanged for access token with account takeover demonstration. Condition 1 (redirect_uri without exact match) and Condition 4 (absent PKCE) confirmed.
H1 #405100 (Bohemia Interactive, accounts.bistudio.com): Allowlist bypass with multi-use authorization codes. The code was captured via allowlist evasion. The same code was replayed after interception successfully. Condition 1 and Condition 2 (multi-use codes) confirmed. OAuth tokens stolen with full demonstration.
H1 #1861974: Path traversal https://app/callback/../attacker accepted by the server. Authorization code captured in the GET log of the attacker's endpoint. The token endpoint did not revalidate the redirect_uri during the code exchange. Condition 1 (traversal accepted) and Condition 3 (token endpoint without revalidation, violating RFC 6749 §4.1.3) confirmed. P2.
H1 #861940 (Semrush): Bypass via parameter manipulation with absent PKCE in the affected flow. Code interception confirmed as exploitable. Condition 1 and Condition 4 confirmed.
The pattern is consistent across all 4 reports. Reports closed as low did not demonstrate effective code capture nor confirm additional conditions. High-severity reports documented the full chain: confirmed bypass plus at least 1 additional condition that makes the code directly exchangeable.
The 5-Condition Matrix and Detection
5 observable conditions determine whether a redirect_uri bypass is exploitable or theoretical. All are verifiable passively before any authenticated request.
Condition 1 (redirect_uri without exact match): submit https://app.example.com/callback%2F..%2Fattacker. The server returning the code to this URI confirms viable path traversal.
Condition 2 (multi-use codes): replay the same authorization code twice at the token endpoint. A second 200 response confirms multi-use. Any captured code can be replayed after interception.
Condition 3 (token endpoint without redirect_uri revalidation): submit a valid code with a redirect_uri different from the one used in the authorization. Success confirms violation of the MUST in RFC 6749 §4.1.3. The code is exchangeable from any capturing URI.
Condition 4 (PKCE not enforced): send the authorization request without code_challenge. Attempt to exchange the code without code_verifier. Access token returned confirms PKCE is ornamental.
Condition 5 (implicit flow active): send response_type=token. The token arrives in the URL fragment. Any third-party resource on the callback page can read the token via Referer.
(MAGO team tool) probes all 5 conditions passively. The probe covers redirect_uri exact match, single-use enforcement, token endpoint revalidation, PKCE method, and exposure via implicit flow.
CVE-2019-3778 in Spring Security OAuth is the reference case for Condition 3. The DefaultRedirectResolver in AuthorizationEndpoint accepted manipulated redirect_uris in the authorization code flow. The code was delivered to the attacker. CVSS 6.5. Affected versions cover Spring Security OAuth 2.0 up to 2.0.17 and 2.3 up to 2.3.5.
Bug bounty triage in this class is binary. The report documents the redirect to the attacker's server, or it documents the captured code and the conditions that make it exchangeable. The first is an open redirect. The second is authorization code interception with measurable impact.
Submit the conditions table in the report, not the redirect description. P1 documents what the server did with the code after it left the legitimate client, not where the browser went.
Top comments (0)