CVE-2026-46715: Flask Security Too Flask-Security-Too OAuth Reauthentication Freshness Bypass Vulnerability
MODERATECVE-2026-46715 is a MODERATE flask-security-too oauth reauthentication freshness bypass vulnerability (CWE-287: Improper Authentication) affecting Flask Security Too libraries in the PyPI ecosystem. The issue involves flask-security-too oauth reauthentication freshness bypass via cross- user oauth identity acceptance. Remediation is available by upgrading affected packages to version 5.8.1.
CVE-2026-46715 at a Glance
How to Fix CVE-2026-46715
To remediate this vulnerability, upgrade all affected Flask Security Too dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.
pip install Flask-Security-Too>=5.8.1
Run the following command in your project directory to verify that all resolved dependencies use the patched release:
pip show Flask-Security-Too
How to Check if You Are Affected
To determine whether your Python environment is affected by CVE-2026-46715, inspect your installed packages using pip:
pip show Flask-Security-Too
Analyze the terminal output to locate any version of Flask Security Too in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 5.8.1), your application is affected.
Note: The pip show Flask-Security-Too command checks currently installed packages in your active Python environment.
Technical Details
Vulnerability Mechanism & Technical Analysis
This vulnerability is classified under CWE-287: Improper Authentication, where when an actor claims to have a given identity, the product does not prove or insufficiently proves that the claim is correct. In Flask Security Too, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.
Source Advisory Statement
CVE-2026-46715 Affected Flask Security Too Versions
1 component(s)| Product / Package | Ecosystem | Affected Versions | Fixed Version |
|---|---|---|---|
|
Flask-Security-Too
|
PyPI |
≥ 5.8.0
< 5.8.1
|
5.8.1
|
References
Frequently Asked Questions
What is CVE-2026-46715?
Which Flask Security Too versions are affected?
What version fixes CVE-2026-46715?
Is Flask-Security-Too affected?
What CWE is associated with CVE-2026-46715?
How can I check PyPI dependencies for CVE-2026-46715?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"schema_version" : "1.4.0",
"id" : "GHSA-97r5-pg8x-p63p",
"modified" : "2026-05-22T17:48:54Z",
"published" : "2026-05-22T17:48:54Z",
"aliases" : [ "CVE-2026-46715" ],
"summary" : "Flask-Security-Too OAuth reauthentication freshness bypass via cross- user OAuth identity acceptance",
"details" : "### Summary\n\n Flask-Security-Too 5.8.0's OAuth reauthentication flow can mark a\n session as fresh after verifying an OAuth account that belongs to a\n different user.\n\n If an attacker can operate an already-authenticated but stale victim\n session, they can complete OAuth verification using their own OAuth\n identity. The victim session is then treated as recently\n reauthenticated, allowing freshness-protected account actions to\n proceed. This was reproduced against the built-in `/change-username`\n route.\n\n ### Details\n\n The issue is in the OAuth verification callback.\n\n `_oauth_response_common()` resolves the OAuth provider identity to a\n Flask-Security user:\n\n - `flask_security/oauth_glue.py:101-108`\n\n `oauth_verify_response()` then accepts any resolved user and updates\n the current session freshness timestamp:\n\n - `flask_security/oauth_glue.py:182-214`\n - `flask_security/oauth_glue.py:201-204`\n\n The missing check is that the OAuth-resolved user must match the\n current authenticated session user. In the failing case:\n\n - current session user: `victim@example.com`\n - OAuth verified user: `attacker@example.com`\n - session marked fresh: yes\n\n So the attacker is not logging in as the victim, but they are\n satisfying the victim session's reauthentication requirement with a\n different account.\n\n ### PoC\n\n Tested version:\n\n - `Flask-Security-Too 5.8.0`\n - tag `5.8.0`\n - commit `08288dff6907e413d848a16aaf43fc2c2b2a3b72`\n\n Used a minimal Flask app with:\n\n ```python\n SECURITY_OAUTH_ENABLE = True\n SECURITY_OAUTH_BUILTIN_PROVIDERS = [\"github\"]\n SECURITY_FRESHNESS = timedelta(seconds=1)\n SECURITY_FRESHNESS_GRACE_PERIOD = timedelta(seconds=0)\n SECURITY_USERNAME_ENABLE = True\n SECURITY_CHANGE_USERNAME = True\n\n The OAuth provider was replaced with a localhost mock provider\n returning attacker@example.com. This avoids hitting a live third-party\n provider while still exercising Flask-Security-Too's real OAuth\n verification handler.\n\n Reproduction steps:\n\n 1. Log in as victim@example.com.\n 2. Wait until the session is no longer fresh.\n 3. Confirm POST /change-username is blocked with 401 and\n reauth_required=true.\n 4. Start OAuth verification with POST /login/oauth-verify-start/\n github.\n 5. Complete the callback with an OAuth identity for\n attacker@example.com.\n 6. Confirm the session is still for victim@example.com, but fs_paa has\n been updated.\n 7. Retry POST /change-username.\n 8. The victim user's username is changed successfully.\n\n Observed result:\n\n {\n \"pre_bypass_status\": 401,\n \"pre_bypass_reauth_required\": true,\n \"attacker_identity\": \"attacker@example.com\",\n \"oauth_verify_response_status\": 302,\n \"post_bypass_change_username_status\": 200,\n \"final_email\": \"victim@example.com\",\n \"final_username\": \"victimowned1777878574\",\n \"direct_impact_verified\": true\n }\n\n Note: CSRF was disabled in the local harness only to keep the test\n focused on the reauthentication check. This is not a CSRF bypass\n report.\n\n This bypasses Flask-Security-Too's freshness/reauthentication\n boundary.\n\n Applications using OAuth verification together with freshness-\n protected account operations may allow a stale victim session to be\n refreshed using a different user's OAuth account. In my test, this\n allowed the victim account's username to be changed through Flask-\n Security-Too's built-in /change-username route.\n\n A likely fix is to reject OAuth verification unless the resolved OAuth\n user matches current_user before updating session[\"fs_paa\"].",
"severity" : [ ],
"affected" : [ {
"package" : {
"ecosystem" : "PyPI",
"name" : "Flask-Security-Too"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "5.8.0"
}, {
"fixed" : "5.8.1"
} ]
} ]
} ],
"references" : [ {
"type" : "WEB",
"url" : "https://github.com/pallets-eco/flask-security/security/advisories/GHSA-97r5-pg8x-p63p"
}, {
"type" : "PACKAGE",
"url" : "https://github.com/pallets-eco/flask-security"
} ],
"database_specific" : {
"cwe_ids" : [ "CWE-287" ],
"severity" : "MODERATE",
"github_reviewed" : true,
"github_reviewed_at" : "2026-05-22T17:48:54Z",
"nvd_published_at" : null
}
}