CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



GHSA-W2J7-F3C6-G8CW

GHSA-w2j7-f3c6-g8cw: Open Redirect Bypass via Parser Differential in Flask-Security

Amit Schendel
Amit Schendel
Senior Security Researcher

Jun 24, 2026·8 min read·2 visits

Executive Summary (TL;DR)

A parser differential between Python's urlsplit() and web browsers allows attackers to bypass subdomain redirect validation in Flask-Security using backslash-based host strings, leading to open redirect attacks.

An open redirect vulnerability exists in Flask-Security versions up to and including 5.8.0. This flaw allows remote, unauthenticated attackers to perform open redirects by exploiting a parser differential between Python's standard library urlsplit() function and modern web browsers when subdomain redirection is allowed.

Vulnerability Overview

The vulnerability resides within the redirection validation mechanism of the Flask-Security integration package. This library offers security features for Flask applications, including user registration, authentication, and password recovery. A common architectural pattern for these applications involves redirecting users to their originally requested path after completing an authentication flow, such as logging in or logging out. The attack surface is exposed through user-controlled parameters, typically named 'next' or 'redirect', which accept destination URLs.

Under specific configurations, such as when SECURITY_REDIRECT_ALLOW_SUBDOMAINS is set to True, the application tries to allow redirects only to authorized subdomains of the main server domain. The validation logic relies on the flask_security.utils.validate_redirect_url() function to verify that the target URL belongs to a trusted domain before issuing the HTTP 302 redirect header. When the application contains this specific setting, it trusts the validation utility to filter out malicious destinations.

This implementation is vulnerable to a parser differential attack that exploits discrepancies between the application server's backend parsing engine and the victim's frontend web browser. Successful exploitation of this vulnerability yields an open redirect bypass, classified under CWE-601. Unauthenticated remote attackers can leverage this flaw to redirect victims to malicious, lookalike domains to capture user credentials or execute secondary web-based attacks.

Root Cause Analysis

The underlying flaw is located in Python's standard library parser function urllib.parse.urlsplit(), which is used directly by Flask-Security's validate_redirect_url(). To decide whether an input URL represents an authorized subdomain, the validation utility extracts the netloc component of the URL. The application then checks if the extracted hostname ends with the configured valid domain, such as '.whitelist.com'.

When an attacker provides a URL containing a backslash ('\') within the authority portion of the URL structure, such as 'http://evil.com\\\\.whitelist.com', Python's parser evaluates the string differently than modern web standards. Specifically, RFC 3986 specifies rules for URL parsing that standard libraries implement with varying degrees of strictness. Python's urlsplit() treats the backslash character as a valid character within the netloc authority block rather than a path separator.

Consequently, the utility parses the entire string 'evil.com\\.whitelist.com' as the hostname. Because this parsed string ends with the suffix '.whitelist.com', the validation logic evaluates the entire host as a legitimate subdomain of the whitelisted domain. The validation function returns True, indicating the URL is safe for redirection, and the backend server issues a 302 Found response containing this URL in the Location header.

Once the client browser receives the HTTP response, the threat materializes. Modern web browsers, conforming to the WHATWG Living Standard for URLs, normalize backslashes inside authority headers to forward slashes ('/') before executing the network request. The browser transforms the location target to 'http://evil.com/.whitelist.com'. The browser then parses 'evil.com' as the true target host and '.whitelist.com' as the path, routing the user to the attacker-controlled server.

Code Analysis and Comparison

To illustrate the architectural defect, we examine the vulnerable code path that processes the redirection check. The validation utility processes user input before transmitting the HTTP redirection header to the client.

# Vulnerable implementation logic within validate_redirect_url()
from urllib.parse import urlsplit
 
def validate_redirect_url(url):
    # The input string is parsed using Python's standard utility
    parsed = urlsplit(url)
    netloc = parsed.netloc
 
    # Subdomain validation checks only if the parsed netloc ends with the base domain
    if SECURITY_REDIRECT_ALLOW_SUBDOMAINS:
        base_domain = app.config["SERVER_NAME"] # e.g., 'whitelist.com'
        if netloc.endswith("." + base_domain):
            return True # Returns True because 'evil.com\\\\.whitelist.com' ends with '.whitelist.com'
    return False

The fix introduced in Flask-Security 5.8.1 changes the handling of authority components by strictly sanitizing characters before running the validation check or by rejecting URLs containing illegal characters in the authority portion. The following conceptual implementation represents the hardened validation logic.

# Hardened validation logic introduced to counter the parser differential
from urllib.parse import urlsplit
 
def validate_redirect_url_patched(url):
    # First, check for characters that cause parser differentials between Python and browsers
    if "\\\\" in url or "%5c" in url.lower():
        # Explicitly reject backslashes to prevent normalization bypasses
        return False
 
    parsed = urlsplit(url)
    netloc = parsed.netloc
 
    # Standard subdomain validation continues after safety checks
    if SECURITY_REDIRECT_ALLOW_SUBDOMAINS:
        base_domain = app.config["SERVER_NAME"]
        if netloc.endswith("." + base_domain):
            return True
    return False

The defensive correction ensures that any occurrence of raw or encoded backslashes within the target URL results in immediate validation failure. By blocking these characters, the application prevents modern browsers from receiving a payload that they would normalize into an external destination. The patch effectively aligns the server-side host parsing model with the client-side browser execution model.

Attack Methodology and Execution

The physical routing of this attack is demonstrated in the diagram below, showing how the backend server and client browser process the path differently.

The exploitation flow requires minimal preparation and can be executed by an unauthenticated remote attacker. The threat actor first identifies a target application running a vulnerable version of Flask-Security with subdomain redirects enabled. The attacker then constructs a malicious URL that points to their infrastructure while appending a suffix that mimics the target host domain.

Using either a raw backslash or a URL-encoded representation ('%5C'), the attacker formats the target URL. An example of a crafted payload is 'http://attacker-controlled.com%5C.target-domain.com/login'. This URL is set as the value for the redirection query parameter, which is commonly named 'next' or 'redirect' in authentication forms.

The attacker distributes this crafted link to target users using phishing emails or social engineering vectors. When a victim clicks the link, they are directed to the legitimate login interface of the target application. Once the victim completes the authentication process, the application validates the redirection parameter, accepts it as safe, and responds with a 302 Found status containing the payload. The client's web browser processes the header, converts the backslash into a forward slash, and forwards the session to the attacker's server.

Impact Assessment

The primary impact of this open redirect vulnerability is the facilitation of highly convincing credential-harvesting campaigns. Because the initial domain in the address bar is the trusted, legitimate host, the user undergoes normal authentication. The subsequent seamless redirection to an external lookalike page can deceive security-conscious users into re-entering their credentials or executing secondary malicious actions on the destination server.

This vulnerability receives a CVSS v3.1 base score of 4.7. The rating reflects the requirement for user interaction, as a victim must initiate the connection by clicking the maliciously crafted link. The scope is designated as changed (S:C) because the security authority shifts from the trusted domain to an untrusted external entity. Confidentiality is rated low (C:L) because OAuth authorization codes, session tokens, or other sensitive parameters appended to the redirect URL can be leaked to the external server's access logs.

While open redirects are often considered low-severity issues, their utility in multi-stage attack chains is significant. Security teams should treat this vulnerability as a high-priority fix in environments where single sign-on (SSO) or OAuth workflows are configured. If the application forwards authentication state tokens via URL parameters, this bypass directly threatens the integrity of those active sessions.

Remediation and Detection Guidance

The most effective and permanent resolution is upgrading Flask-Security to version 5.8.1 or higher. The maintainers implemented robust parsing filters in this version to eliminate parser differentials. When upgrading, deployment teams must ensure that transit dependencies such as Werkzeug are also updated to compatible versions.

If upgrading is not immediately possible, security teams must deploy defensive workarounds. The simplest administrative fix is setting SECURITY_REDIRECT_ALLOW_SUBDOMAINS = False in the application configuration. This setting restricts redirection exclusively to the exact domain defined in SERVER_NAME or local relative paths, thereby bypassing the vulnerable subdomain validation routines entirely.

Alternatively, developers can implement custom validation middleware to filter incoming redirection parameters. The following Python code snippet demonstrates an effective filtering strategy to reject unsafe inputs before Flask-Security processes them.

from flask import abort, request
 
def sanitize_redirects_middleware():
    target = request.args.get("next", "")
    # Intercept and reject any redirection parameters with path-normalization indicators
    if "\\\\" in target or "2f" in target.lower() or "5c" in target.lower():
        abort(400, "Insecure URL redirect requested.")

To detect active exploitation attempts, operations teams should audit application server access logs. Standard queries should scan for requests to login or redirection endpoints containing backslashes or their hex-encoded equivalents within parameter values. Intrusion detection systems (IDS) should also run rules that flag outbound requests with HTTP 302 statuses redirecting to unrecognized destination servers containing backslashes.

Technical Appendix

CVSS Score
4.7/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:N/A:N

Affected Systems

Flask-Security with SECURITY_REDIRECT_ALLOW_SUBDOMAINS enabled

Affected Versions Detail

Product
Affected Versions
Fixed Version
Flask-Security
pallets-eco
<= 5.8.05.8.1
AttributeDetail
CWE IDCWE-601
Attack VectorNetwork (AV:N)
CVSS Score4.7 (Medium)
EPSS ScoreN/A
ImpactOpen Redirect
Exploit StatusProof-of-Concept
KEV StatusNot Listed

MITRE ATT&CK Mapping

T1566Phishing
Initial Access
T1204.001User Execution: Malicious Link
Execution
CWE-601
URL Redirection to Untrusted Site ('Open Redirect')

A web application accepts a user-controlled input that specifies a link to an external site, and uses that link in a Redirect.

Vulnerability Timeline

Official GitHub Security Advisory published under ID GHSA-w2j7-f3c6-g8cw
2026-06-23
Official release of Flask-Security version 5.8.1 containing code remediation
2026-06-25

References & Sources

  • [1]GitHub Security Advisory GHSA-w2j7-f3c6-g8cw
  • [2]OSV Vulnerability Database Registry
  • [3]National Vulnerability Database (NVD) Analysis for CVE-2023-49438
  • [4]GitLab Advisory Entry for Flask-Security Open Redirect Class
  • [5]GitHub Advisories Main Entry Portal
Related Vulnerabilities
CVE-2023-49438

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•3 minutes ago•GHSA-WCMJ-X466-56MM
6.1

GHSA-WCMJ-X466-56MM: Arbitrary File Write via UNIX Symbolic Link Following in OpenTofu

A UNIX symbolic link following vulnerability exists in the provider cache installation mechanism of OpenTofu. This flaw allows an attacker with control over the repository files to write files outside of the intended workspace boundary during initialization.

Amit Schendel
Amit Schendel
0 views•6 min read
•about 2 hours ago•CVE-2026-48507
7.1

CVE-2026-48507: Incorrect Authorization in Snipe-IT Bulk User Edit and Merge Features

An incorrect authorization vulnerability (CWE-863) in Snipe-IT versions prior to 8.6.0 allows authenticated, low-privileged users with granular 'users.edit' permissions to modify restricted user flags ('activated' and 'ldap_import') and merge high-privileged administrator accounts into standard user accounts. This allows an attacker to lock administrators out of the system or completely hijack administrator accounts.

Amit Schendel
Amit Schendel
2 views•8 min read
•about 5 hours ago•CVE-2026-49205
6.5

CVE-2026-49205: Missing Authorization in phpMyFAQ Public REST API Write Endpoints

An incomplete security patch for CVE-2026-24421 in phpMyFAQ allows authenticated low-privileged users to bypass role-based access controls. While the initial patch addressed missing authorization in the BackupController, it left four critical write-enabled endpoints vulnerable. This allows remote attackers with a valid low-privilege API token to perform unauthorized data modifications, creating categories, creating FAQs, updating FAQs, and injecting questions directly into the database.

Amit Schendel
Amit Schendel
6 views•5 min read
•about 14 hours ago•GHSA-74P7-6H78-GW8P
8.6

GHSA-74P7-6H78-GW8P: Multiple Critical Security Flaws in skillctl Agent-Skill Manager

An in-depth security audit of the skillctl command-line package manager revealed five critical and high-severity security vulnerabilities. The identified flaws span parameter-level command argument injection via the source_sha parameter, uncontrolled resource consumption (Denial of Service) through unnamed UNIX FIFOs and character devices, directory path traversal in the destination argument, commit-message trailer forgery via newline injection in skill names, and local credential exfiltration leveraging UNIX hardlinks. These vulnerabilities represent significant vectors for workstation compromise when executing agentic tasks in repositories containing untrusted files or pull requests. Remediation was introduced in version v0.1.3.

Alon Barad
Alon Barad
6 views•6 min read
•about 18 hours ago•CVE-2026-48153
8.5

CVE-2026-48153: Server-Side Request Forgery in Budibase OAuth2 SDK

CVE-2026-48153 is a Server-Side Request Forgery (SSRF) vulnerability in the Budibase OAuth2 SDK prior to version 3.39.0. It allows authenticated low-privileged users to bypass outbound network security blacklists and send arbitrary requests to internal subnets or cloud metadata services.

Alon Barad
Alon Barad
10 views•7 min read
•about 19 hours ago•GHSA-GHMH-JHMJ-WCMF
5.1

GHSA-GHMH-JHMJ-WCMF: Plaintext Storage of Enrollment Tokens at Rest in SQLite in nebula-mesh

The self-hosted Slack Nebula VPN control plane, nebula-mesh, stored high-privilege enrollment tokens in plaintext inside its SQLite database. This flaw allowed any adversary with read access to the database to retrieve pending tokens and enroll unauthorized hosts into the secure VPN mesh.

Alon Barad
Alon Barad
6 views•8 min read