Mar 10, 2026·6 min read·6 visits
Unauthenticated ReDoS in Parse Server LiveQuery allows attackers to halt the Node.js event loop via crafted $regex subscriptions, causing a complete denial of service.
Parse Server versions prior to 8.6.11 and 9.5.0-alpha.14 contain a critical vulnerability in the LiveQuery component. The application evaluates client-provided regular expressions directly on the single-threaded Node.js event loop without adequate execution limits. Unauthenticated attackers can submit crafted subscriptions that cause exponential backtracking, exhausting CPU resources and resulting in a complete denial of service.
Parse Server provides a LiveQuery feature that allows client applications to subscribe to real-time data changes via WebSockets. To filter the data stream, clients construct query objects containing constraints, which the server evaluates whenever a relevant database object is created or updated. Unauthenticated users, requiring only the public applicationId and javascriptKey, can submit complex constraints including regular expressions.
The vulnerability is classified as CWE-1333 (Inefficient Regular Expression Complexity) and specifically affects the LiveQuery subscription matching engine. While Parse Server routes standard REST and GraphQL regular expression queries to the underlying database engine, the LiveQuery module evaluates subscription constraints independently. This architectural decision forces the application layer to process potentially untrusted input directly.
LiveQuery evaluates these regular expressions on the main Node.js application layer. Node.js operates on a single-threaded event loop, meaning that any synchronous operation consuming excessive CPU cycles prevents the execution of all other concurrent tasks. An attacker can leverage this architecture to force the server into a computationally expensive operation, effectively rendering the entire backend unresponsive to all users.
The root cause resides in the src/LiveQuery/QueryTools.js file, specifically within the matchesKeyConstraints function. This function determines whether a modified database object meets the criteria of an active LiveQuery subscription. Prior to the patch, the function utilized the native JavaScript RegExp.test() method to evaluate client-provided regex patterns against object values.
The implementation failed to enforce execution time limits or validate the structural complexity of the untrusted regular expressions. When a regex pattern contains nested quantifiers, such as (a+)+b, it introduces the potential for exponential backtracking. If the engine evaluates this pattern against a string that nearly matches but fails at the final character, it attempts to process every possible permutation of the input.
This behavior causes the execution time of RegExp.test() to grow exponentially relative to the length of the input string. Because the evaluation occurs synchronously on the main thread, the Node.js event loop remains locked until the computation completes. During this period, the Parse Server instance cannot process incoming API requests, health checks, or other WebSocket messages, resulting in a denial of service.
Prior to the patch, QueryTools.js blindly instantiated and executed regular expressions constructed from untrusted client input. The vulnerable implementation directly applied RegExp(pattern, modifiers).test(value) within the main execution thread. This direct invocation provided no mechanism to interrupt the evaluation if it consumed excessive computational resources.
The remediation introduced in PR #10118 replaces the direct evaluation with an isolated execution environment. Parse Server now utilizes the native Node.js vm module to sandbox the regex evaluation. The development team implemented vm.Script.runInContext alongside a strict execution timeout mechanism to prevent the event loop from blocking indefinitely.
// Conceptual representation of the patched evaluation mechanism
const vm = require('vm');
const context = vm.createContext({ targetString: value, pattern: regexPattern });
const script = new vm.Script('new RegExp(pattern).test(targetString)');
try {
// Evaluation terminates if it exceeds the specified timeout
const isMatch = script.runInContext(context, { timeout: liveQuery.regexTimeout });
return isMatch;
} catch (err) {
// Timeout triggers an exception, protecting the event loop
return false;
}The patch introduces a liveQuery.regexTimeout configuration parameter, defaulting to 100 milliseconds. If the regex engine fails to complete its evaluation within this window, the vm context forcibly terminates the execution. The engine catches the resulting exception and treats the match as false, ensuring the server continues processing subsequent requests.
Exploitation requires network access to the Parse Server WebSocket endpoint and knowledge of the application keys, which are typically distributed within client-side application bundles. The attacker initiates a WebSocket connection and issues a LiveQuery subscription request targeting any accessible data class. The attacker embeds a malicious regular expression directly into the query constraints.
// Step 1: Subscribe with a malicious regex pattern
const query = new Parse.Query('TestObject');
query._addCondition('field', '$regex', '(a+)+b');
const subscription = query.subscribe();Once the server registers the subscription, the attacker must trigger the evaluation phase. They achieve this by inserting or updating a record in the targeted class with a payload explicitly designed to maximize backtracking cycles. The payload consists of a long string of repeating characters ending in a non-matching character.
// Step 2: Trigger the evaluation with a crafted string
const obj = new Parse.Object('TestObject');
obj.set('field', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaac');
await obj.save();Upon processing the database update, the LiveQuery engine iterates through all active subscriptions to determine routing logic. As it evaluates the attacker's malicious regex against the crafted string, the synchronous operation consumes all available CPU cycles. The server requires manual intervention or an external supervisor restart to restore availability.
The vulnerability results in a complete denial of service for the entire Parse Server instance. Node.js handles all concurrent client connections on a single thread, meaning the event loop blockage prevents the server from processing REST API requests, GraphQL queries, and WebSocket operations. All downstream client applications reliant on the backend experience immediate connection timeouts.
The CVSS v4.0 score of 8.2 reflects the high availability impact and the lack of required privileges. The attack vector is strictly network-based, and the exploitation process requires low technical complexity. An attacker can repeatedly execute the exploit via an automated script, rendering the backend persistently unavailable and causing significant operational disruption.
This vulnerability strictly impacts system availability; it does not compromise data confidentiality or integrity. Attackers cannot utilize this vector to extract database records, modify existing data, or achieve remote code execution. Despite the lack of data exposure, the ease of triggering a persistent outage makes this a critical risk for production environments.
Administrators must update Parse Server to version 8.6.11 or 9.5.0-alpha.14 depending on the active release branch. These versions implement the vm sandbox isolation and enforce the 100-millisecond execution timeout by default. No further configuration changes are required to activate the primary protection mechanism.
If immediate patching is technically infeasible, administrators can deploy a Cloud Code mitigation to temporarily secure the environment. By registering a beforeSubscribe trigger on the affected classes, developers can inspect the incoming query structure and reject any subscription attempt that includes the $regex operator.
Parse.Cloud.beforeSubscribe('MyClass', request => {
const where = request.query._where || {};
for (const value of Object.values(where)) {
if (value && typeof value === 'object' && value.$regex) {
throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, '$regex is currently disabled');
}
}
});Post-upgrade, security teams must verify that the liveQuery.regexTimeout configuration remains at its default value or a securely defined threshold. The application logs a security warning if administrators explicitly set this value to 0, which disables the timeout protection entirely. Routine configuration audits should ensure this setting is not inadvertently modified during deployment scaling.
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
Parse Server parse-community | < 8.6.11 | 8.6.11 |
Parse Server parse-community | >= 9.0.0, < 9.5.0-alpha.14 | 9.5.0-alpha.14 |
| Attribute | Detail |
|---|---|
| Vulnerability Type | CWE-1333: Inefficient Regular Expression Complexity |
| Attack Vector | Network (WebSocket Subscription) |
| Authentication Required | None (Requires public application keys) |
| CVSS v4.0 Score | 8.2 (High) |
| Impact | Complete Denial of Service |
| Exploit Status | Proof of Concept Available |
| CISA KEV Status | Not Listed |
The application processes a regular expression containing structural characteristics that result in exponential evaluation time when evaluating specific inputs.