Flask-Security-Too OAuth reauthentication freshness bypass via cross- user OAuth identity acceptance
Description
Summary
Flask-Security-Too 5.8.0's OAuth reauthentication flow can mark a session as fresh after verifying an OAuth account that belongs to a different user.
If an attacker can operate an already-authenticated but stale victim session, they can complete OAuth verification using their own OAuth identity. The victim session is then treated as recently reauthenticated, allowing freshness-protected account actions to proceed. This was reproduced against the built-in /change-username route.
Details
The issue is in the OAuth verification callback.
_oauth_response_common() resolves the OAuth provider identity to a Flask-Security user:
flask_security/oauth_glue.py:101-108
oauth_verify_response() then accepts any resolved user and updates the current session freshness timestamp:
flask_security/oauth_glue.py:182-214flask_security/oauth_glue.py:201-204
The missing check is that the OAuth-resolved user must match the current authenticated session user. In the failing case:
- current session user:
victim@example.com - OAuth verified user:
attacker@example.com - session marked fresh: yes
So the attacker is not logging in as the victim, but they are satisfying the victim session's reauthentication requirement with a different account.
PoC
Tested version:
Flask-Security-Too 5.8.0- tag
5.8.0 - commit
08288dff6907e413d848a16aaf43fc2c2b2a3b72
Used a minimal Flask app with:
SECURITY_OAUTH_ENABLE = True
SECURITY_OAUTH_BUILTIN_PROVIDERS = ["github"]
SECURITY_FRESHNESS = timedelta(seconds=1)
SECURITY_FRESHNESS_GRACE_PERIOD = timedelta(seconds=0)
SECURITY_USERNAME_ENABLE = True
SECURITY_CHANGE_USERNAME = True
The OAuth provider was replaced with a localhost mock provider
returning attacker@example.com. This avoids hitting a live third-party
provider while still exercising Flask-Security-Too's real OAuth
verification handler.
Reproduction steps:
1. Log in as victim@example.com.
2. Wait until the session is no longer fresh.
3. Confirm POST /change-username is blocked with 401 and
reauth_required=true.
4. Start OAuth verification with POST /login/oauth-verify-start/
github.
5. Complete the callback with an OAuth identity for
attacker@example.com.
6. Confirm the session is still for victim@example.com, but fs_paa has
been updated.
7. Retry POST /change-username.
8. The victim user's username is changed successfully.
Observed result:
{
"pre_bypass_status": 401,
"pre_bypass_reauth_required": true,
"attacker_identity": "attacker@example.com",
"oauth_verify_response_status": 302,
"post_bypass_change_username_status": 200,
"final_email": "victim@example.com",
"final_username": "victimowned1777878574",
"direct_impact_verified": true
}
Note: CSRF was disabled in the local harness only to keep the test
focused on the reauthentication check. This is not a CSRF bypass
report.
This bypasses Flask-Security-Too's freshness/reauthentication
boundary.
Applications using OAuth verification together with freshness-
protected account operations may allow a stale victim session to be
refreshed using a different user's OAuth account. In my test, this
allowed the victim account's username to be changed through Flask-
Security-Too's built-in /change-username route.
A likely fix is to reject OAuth verification unless the resolved OAuth
user matches current_user before updating session["fs_paa"].AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Flask-Security-Too 5.8.0 OAuth reauthentication flow does not verify that the OAuth user matches the session user, allowing an attacker to freshen a victim's stale session.
Vulnerability
Flask-Security-Too version 5.8.0 contains a missing user identity check in the OAuth reauthentication flow. The functions _oauth_response_common() (at flask_security/oauth_glue.py:101-108) and oauth_verify_response() (at flask_security/oauth_glue.py:182-214, specifically 201-204) resolve an OAuth provider identity to a Flask-Security user and then update the current session's freshness timestamp without verifying that the resolved user matches the already-authenticated session user [1][2]. This flaw is reachable when the application enables OAuth features (e.g., SECURITY_OAUTH_ENABLE = True) and has freshness-protected endpoints such as the built-in /change-username route enabled [1][2].
Exploitation
An attacker must have control over an already-authenticated but stale victim session (the victim's session cookie). The attacker first logs in as their own OAuth identity (e.g., attacker@example.com) while using the victim's session. The session's authenticated user remains victim@example.com, but the OAuth verification callback marks the session as fresh because it accepts the attacker's OAuth identity [1][2]. The steps are: (1) log in as victim, (2) wait for the session to become stale, (3) trigger the OAuth verification flow with the attacker's OAuth account, (4) the session is now marked fresh, allowing freshness-protected actions [1][2].
Impact
An attacker who can operate a stale victim session can bypass reauthentication requirements and perform freshness-protected account actions, such as changing the victim's username via /change-username, without knowing the victim's password or having further authorization. This undermines the security guarantee that sensitive operations require recent authentication. The attacker does not gain access to the victim's account; they only exploit the victim's existing session [1][2].
Mitigation
No official fix has been released as of the publication date (2026-05-22). The affected version is Flask-Security-Too 5.8.0. Users should disable OAuth-based reauthentication or restrict freshness-protected routes until a patched version is made available. Workarounds include not using the OAuth reauthentication feature, or implementing a custom validation callback that ensures the OAuth-resolved user matches the current session user [1][2]. The CVE is not listed in CISA's Known Exploited Vulnerabilities (KEV) catalog at the time of writing.
AI Insight generated on May 22, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
1- Range: >= 5.8.0, < 5.8.1
Patches
0No patches discovered yet.
Vulnerability mechanics
AI mechanics synthesis has not run for this CVE yet.
References
2News mentions
0No linked articles in our index yet.