Mar 24, 2026·7 min read·2 visits
A race condition in Parse Server allows an attacker to bypass the single-use restriction of MFA recovery codes by sending concurrent login requests, allowing multiple sessions to be established with one code.
Parse Server versions prior to 8.6.60 and 9.6.0-alpha.54 contain a Time-of-check Time-of-use (TOCTOU) race condition in the Multi-Factor Authentication (MFA) recovery mechanism. By issuing concurrent login requests, an attacker possessing a user's password and a single valid MFA recovery code can establish multiple active sessions, bypassing the intended single-use restriction of the recovery code.
Parse Server is a widely deployed open-source Node.js backend framework. It provides a comprehensive authentication system, including support for Multi-Factor Authentication (MFA) and single-use recovery codes. These recovery codes serve as an emergency fallback mechanism when a user loses access to their primary secondary authentication device.
The vulnerability, identified as CVE-2026-33624, is a Time-of-check Time-of-use (TOCTOU) race condition within the MFA recovery code consumption logic. The flaw exists in the /login endpoint request handling, specifically within the src/Routers/UsersRouter.js component.
When a user authenticates using a recovery code, the system must validate the code and subsequently remove it from the user's account to enforce its single-use nature. However, the lack of transaction isolation or optimistic locking between the validation and deletion phases allows an attacker to exploit the brief temporal window between these two operations.
An attacker who successfully executes this race condition can establish multiple valid session tokens using only one recovery code. This behavior defeats the fundamental security property of a single-use authentication artifact, although the attacker must already possess the user's primary credentials and at least one valid recovery code.
The root cause of this vulnerability is a classic CWE-367: Time-of-check Time-of-use (TOCTOU) race condition. The underlying issue stems from a non-atomic implementation of state validation and subsequent state mutation within an asynchronous Node.js environment.
When a login request arrives with an MFA recovery code, the application reads the user's current authData from the backend database. This data includes an array of valid recovery codes. The application checks if the provided code exists in this array (Time-of-Check). If the validation passes, the application constructs a new authData object with the used code removed and issues an asynchronous database update (Time-of-Use) to persist this new state.
Because Parse Server operates asynchronously and processes concurrent incoming requests in parallel, multiple requests can perform the database read operation before any single request completes the database write operation. Consequently, all parallel requests observe the initial state where the recovery code remains valid.
The diagram above illustrates the race window. Request 1 and Request 2 both complete the read phase before Request 1 initiates the write phase. The database adapter relies purely on the user's objectId for the update query, meaning it blindly overwrites the row with the newly computed array, unaware that another transaction might be acting on the same initial state.
The flaw resides within the authentication data processing logic in src/Routers/UsersRouter.js. In the pre-patch implementation, the database update command filters the target user record exclusively by objectId.
// Pre-patch logic (simplified)
if (validatedAuthData && Object.keys(validatedAuthData).length) {
await req.config.database.update(
'_User',
{ objectId: user.objectId }, // VULNERABLE: Lacks state constraints
{ authData: validatedAuthData },
{}
);
}This code executes an unconditional overwrite of the authData field. The query does not guarantee that the authData array in the database matches the array that was originally read and validated.
The remediation introduces an optimistic locking mechanism. The patch modifies the query object to include the original state of the target fields.
// Post-patch logic (simplified)
const query = { objectId: user.objectId };
if (user.authData) {
for (const provider of Object.keys(validatedAuthData)) {
const original = user.authData[provider];
if (original && typeof original === 'object') {
for (const [field, value] of Object.entries(original)) {
// Optimistic locking: check if the array state has changed
if (Array.isArray(value) && JSON.stringify(value) !== JSON.stringify(validatedAuthData[provider]?.[field])) {
query[`authData.${provider}.${field}`] = value; // SECURE: Query includes prior state
}
}
}
}
}
await req.config.database.update('_User', query, { authData: validatedAuthData }, {});By appending query["authData.mfa.recovery"] = value, the database update will only match the record if the recovery array remains unmodified. If a parallel request has already consumed the token and altered the array, the subsequent database update will silently fail to match the row, preventing the secondary session creation.
Exploitation of this TOCTOU vulnerability requires the attacker to fulfill specific prerequisites. The attacker must possess the victim's valid username and password. Additionally, the attacker must have obtained exactly one valid MFA recovery code belonging to the victim.
The attack is executed by orchestrating multiple concurrent HTTP POST requests to the /login API endpoint. The payload for each request must be identical, encapsulating the valid credentials and the targeted recovery code.
{
"username": "victim_user",
"password": "victim_password",
"authData": {
"mfa": {
"token": "RECOVERY_CODE_1"
}
}
}An attacker utilizes a tool capable of high-concurrency request generation, such as Burp Suite Intruder or a custom Python script utilizing the asyncio framework. By dispatching a batch of 10 to 50 requests within a millisecond window, the attacker maximizes the probability of multiple threads executing the validation block prior to the first thread finalizing the database write.
The server responds with HTTP 200 OK for every request that wins the race. Each successful response body contains a uniquely generated sessionToken. The attacker can subsequently utilize these distinct session tokens to establish multiple persistent access sessions across different devices or IP addresses.
The official severity for CVE-2026-33624 is designated as Low, carrying a CVSS 4.0 score of 2.1. The vector string CVSS:4.0/AV:N/AC:H/AT:P/PR:H/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N accurately reflects the constrained nature of this vulnerability.
The Privileges Required (PR) metric is High because the vulnerability cannot be triggered anonymously. The attacker must possess verified knowledge of the user's primary credentials and a functional secondary authentication factor. The Attack Complexity (AC) is High due to the precise millisecond timing required to win the race condition window.
The primary security impact is a localized integrity violation. The vulnerability does not directly expose sensitive data or facilitate arbitrary code execution. Instead, it subverts a specific access control mechanism designed to restrict credential reuse.
Despite the low severity score, the vulnerability complicates post-incident response efforts. If an attacker leverages this flaw to generate redundant session tokens, revoking a single known compromised session may leave secondary sessions active. System administrators must ensure all active sessions for a compromised user are globally invalidated.
The maintainers of Parse Server have addressed this vulnerability through the implementation of optimistic locking in the authentication pipeline. Organizations utilizing Parse Server must update their deployments to patched versions.
The vulnerability is fully resolved in Parse Server version 8.6.60 and Parse Server version 9.6.0-alpha.54. Deployments running any version within the 8.x branch prior to 8.6.60, or the 9.x branch prior to 9.6.0-alpha.54, remain vulnerable to this race condition.
Implementing the patch necessitates verification of the underlying database adapters. The optimistic locking mechanism utilizes dot-notation queries against nested JSON arrays. Administrators must verify that their instances of parse-server-mongodb-adapter or parse-server-postgres-adapter correctly support dot-notation querying as introduced in the upstream patch commits.
For environments where immediate patching is prohibited by change management freezes, no direct configuration workaround exists within Parse Server to prevent the race condition. Detection strategies should focus on monitoring authentication logs for high-frequency concurrent login attempts targeting the same user account from identical IP addresses.
CVSS:4.0/AV:N/AC:H/AT:P/PR:H/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
parse-server parse-community | < 8.6.60 | 8.6.60 |
parse-server parse-community | >= 9.0.0, < 9.6.0-alpha.54 | 9.6.0-alpha.54 |
| Attribute | Detail |
|---|---|
| Vulnerability Class | Time-of-check Time-of-use (TOCTOU) Race Condition |
| CWE ID | CWE-367 |
| CVSS v4.0 Score | 2.1 (Low) |
| Attack Vector | Network |
| Exploit Status | Proof of Concept (PoC) Available |
| CISA KEV | Not Listed |
Time-of-check Time-of-use (TOCTOU) Race Condition