Submit #570441: meteor https://www.meteor.com/ <=3.2.1 Inefficient Regular Expression Complexityinfo

Titlemeteor https://www.meteor.com/ <=3.2.1 Inefficient Regular Expression Complexity
Description# ReDoS Vulnerability in ddp-server/_clientAddress via x-forwarded-for Header **Vulnerability Details:** * **Type:** Regular Expression Denial of Service (ReDoS) * **Affected Component:** `packages/ddp-server/livedata_server.js`, specifically within the `Session.prototype._clientAddress` method. * **Vulnerable Code Snippet:** ```javascript forwardedFor = forwardedFor.trim().split(/\s*,\s*/); ``` * **Problematic Regex:** `/\s*,\s*/` **Condition for Exploitation:** This vulnerability can be triggered only when the Meteor server's environment variable `HTTP_FORWARDED_COUNT` is set to an integer value greater than 0. **Input Source & Impact:** When the condition above is met, the code processes the `x-forwarded-for` HTTP header value. A malicious client can send a crafted `x-forwarded-for` header containing a large number of whitespace characters followed by a non-comma character. Due to catastrophic backtracking in the vulnerable regex, this can cause the server process handling the DDP connection to consume excessive CPU, leading to a Denial of Service. **Proof of Concept (PoC):** 1. Set the `HTTP_FORWARDED_COUNT` environment variable to `1` (or higher) on the Meteor server. 2. Initiate a DDP connection to the server. 3. Include an `x-forwarded-for` HTTP header with a value consisting of a very large number of space characters followed by a non-comma character (e.g., `' '.repeat(LARGE_NUMBER) + 'a'`). 4. Observe the server process for high CPU usage and unresponsiveness. **Suggested Fix:** To mitigate this ReDoS risk and improve clarity, replace the regex-based split with a safer approach using `String.prototype.split` with a simple delimiter and `Array.prototype.map` for trimming: ```diff // In packages/ddp-server/livedata_server.js, within Session.prototype._clientAddress method // Original vulnerable line: - forwardedFor = forwardedFor.trim().split(/\s*,\s*/); // Suggested fix: + // Trim the entire string (already done before this point in the original code) + let parts = forwardedFor.split(','); + // Trim each part and filter out empty strings + forwardedFor = parts.map(part => part.trim()).filter(part => part.length > 0); + + // Adapt the subsequent logic to use the 'parts' array instead of the direct result of split. + // Example assuming the original code intended to get the Nth-to-last element: + let clientAddress = null; + if (httpForwardedCount <= forwardedFor.length) { + clientAddress = forwardedFor[forwardedFor.length - httpForwardedCount]; + } + // return clientAddress; // (Adjust based on actual return logic needed)
Source⚠️ https://github.com/meteor/meteor/pull/13721
User
 DayShift (UID 80963)
Submission05/03/2025 03:29 (12 months ago)
Moderation05/15/2025 09:13 (12 days later)
StatusAccepted
VulDB entry309029 [Meteor up to 3.2.1 livedata_server.js Object.assign forwardedFor redos]
Points20

Want to know what is going to be exploited?

We predict KEV entries!