CVE-2025-62379
Reflex open redirect on /auth-codespace via unvalidated `redirect_to` param.
- CVSS 3.1
- CWE-601
- Input Validation and Sanitization
- Remote
Reflex is a library to build full-stack web apps in pure Python. In versions 0.5.4 through 0.8.14, the /auth-codespace endpoint automatically assigns the redirect_to query parameter value directly to client-side links without any validation and triggers automatic clicks when the page loads in a GitHub Codespaces environment. This allows attackers to redirect users to arbitrary external URLs. The vulnerable route is only registered when a Codespaces environment is detected, and the detection is controlled by environment variables. The same behavior can be activated in production if the GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN environment variable is set. The vulnerability occurs because the code assigns the redirect_to query parameter directly to a.href without any validation and immediately triggers a click (automatic navigation), allowing users to be sent to arbitrary external domains. The execution condition is based on the presence of a sessionStorage flag, meaning it triggers immediately on first visits or in incognito/private browsing windows, with no server-side origin/scheme whitelist or internal path enforcement defenses in place. This issue has been patched in version 0.8.15. As a workaround, users can ensure that GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN is not set in a production environment.
- CWE
- CWE-601
- CVSS base score
- 3.1
- Published
- 2025-10-15
- OWASP
- A01 Broken Access Control
- Orthogonal defect classification
- Checking
- Code defect classification
- Missing Check
- Category
- Input Validation and Sanitization
- Subcategory
- Open Redirects
- Accessibility scope
- Remote
- Impact
- Information Disclosure
- Affected component
- Reflex
- Fixed by upgrading
- Yes
Solution
Upgrade to Reflex version 0.8.15.
Vulnerable code sample
import os
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
# This is a simplified representation of the vulnerable code that would exist
# within the Reflex framework's internals. It uses FastAPI for demonstration.
app = FastAPI()
def _is_in_codespaces_environment() -> bool:
"""
Simulates the detection of a GitHub Codespaces environment by checking for
a specific environment variable, as described in the CVE.
"""
# The vulnerability is activated if this environment variable is set.
return "GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN" in os.environ
def _add_vulnerable_auth_route(app: FastAPI):
"""
Conditionally registers the vulnerable /auth-codespace endpoint.
"""
# This HTML and JavaScript payload is sent to the client. It contains
# the client-side logic that leads to the open redirect vulnerability.
VULNERABLE_CLIENT_SIDE_CODE = """
<!DOCTYPE html>
<html>
<head>
<title>Authenticating...</title>
</head>
<body>
<p>Please wait, redirecting...</p>
<script>
// The logic is wrapped in a sessionStorage check, causing it to trigger
// on a user's first visit during a session.
if (!sessionStorage.getItem('authRedirectAttempted')) {
sessionStorage.setItem('authRedirectAttempted', 'true');
// The 'redirect_to' query parameter is read from the browser's URL.
const urlParams = new URLSearchParams(window.location.search);
const redirectTo = urlParams.get('redirect_to');
if (redirectTo) {
// VULNERABILITY: The 'redirectTo' value is assigned directly to the
// href attribute of a link element without any validation or
// sanitization. An attacker can supply any URL here, including
// external malicious sites or javascript: URIs.
const link = document.createElement('a');
link.href = redirectTo;
// VULNERABILITY: The link is clicked programmatically, causing an
// automatic and immediate redirect to the attacker-controlled URL.
link.click();
}
}
</script>
</body>
</html>
"""
@app.get("/auth-codespace", response_class=HTMLResponse, include_in_schema=False)
async def handle_auth_codespace(request: Request):
"""
This endpoint serves the vulnerable client-side script that performs
an unvalidated redirect based on the 'redirect_to' query parameter.
"""
return HTMLResponse(content=VULNERABLE_CLIENT_SIDE_CODE)
# In the main application startup logic of the framework, this check
# would be performed to decide whether to register the vulnerable route.
if _is_in_codespaces_environment():
_add_vulnerable_auth_route(app)
# To run this example for demonstration:
# 1. Install dependencies: pip install fastapi uvicorn
# 2. Set the environment variable to activate the route:
# export GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN=example.com
# 3. Run the server: uvicorn your_script_name:app --reload
# 4. Open a browser (preferably in incognito mode) to the vulnerable URL:
# http://127.0.0.1:8000/auth-codespace?redirect_to=https://example.com
# (You will be redirected to example.com)Patched code sample
def get_sanitized_redirect_path(redirect_to: str | None) -> str:
"""
Sanitizes a redirect path to prevent open redirect vulnerabilities.
This function represents the fix applied to the vulnerable endpoint, which
previously used the `redirect_to` query parameter without validation.
The fix ensures the path is always relative to the current domain by checking
if it starts with '/'. This prevents attackers from providing external URLs
(e.g., "//evil.com" or "https://evil.com").
If the provided path is None, empty, or does not start with '/', the function
defaults to a safe root path '/'.
Args:
redirect_to: The untrusted redirect path from a request's query parameter.
Returns:
A sanitized, safe redirect path that is guaranteed to be relative.
"""
# If no redirect path is provided, default to the root.
if not redirect_to:
return "/"
# --- THE FIX ---
# The vulnerability was that the `redirect_to` string was used directly.
# The fix is to validate that the path is a local, relative path by
# checking if it starts with a '/'. If it doesn't, we discard the
# unsafe value and fall back to the safe root path.
if not redirect_to.startswith("/"):
return "/"
# If the path is valid (starts with '/'), it can be safely used.
return redirect_to
# --- Demonstration of the fix ---
# 1. Malicious input attempting to redirect to an external domain.
# The vulnerable code would have used "//evil.com" directly.
malicious_url_1 = "//evil.com"
sanitized_url_1 = get_sanitized_redirect_path(malicious_url_1)
# print(f"Input: '{malicious_url_1}' -> Sanitized: '{sanitized_url_1}'")
# Expected Output: Sanitized: '/'
# 2. Malicious input with a full URL scheme.
# The vulnerable code would have used "http://evil.com" directly.
malicious_url_2 = "http://evil.com"
sanitized_url_2 = get_sanitized_redirect_path(malicious_url_2)
# print(f"Input: '{malicious_url_2}' -> Sanitized: '{sanitized_url_2}'")
# Expected Output: Sanitized: '/'
# 3. Legitimate input for an internal redirect.
# This is considered safe and is allowed to pass through.
legitimate_path = "/dashboard/settings"
sanitized_path = get_sanitized_redirect_path(legitimate_path)
# print(f"Input: '{legitimate_path}' -> Sanitized: '{sanitized_path}'")
# Expected Output: Sanitized: '/dashboard/settings'
# 4. Empty or missing input.
# The function defaults to a safe path.
empty_path = ""
default_path_1 = get_sanitized_redirect_path(empty_path)
default_path_2 = get_sanitized_redirect_path(None)
# print(f"Input: '' -> Sanitized: '{default_path_1}'")
# print(f"Input: None -> Sanitized: '{default_path_2}'")
# Expected Output: Sanitized: '/'Payload
/auth-codespace?redirect_to=https://malicious-website.com
Cite this entry
@misc{vaitp:cve202562379,
title = {{Reflex open redirect on /auth-codespace via unvalidated `redirect_to` param.}},
author = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
year = {2025},
note = {VAITP Python Vulnerability Dataset, entry CVE-2025-62379},
howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2025-62379/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.
The supreme art of war is to subdue the enemy without fighting.
Sun Tzu – “The Art of War”
:: Shaping the future through research and ingenuity ::
