Mar 10, 2026·6 min read·4 visits
Unauthenticated remote attackers can cause a Denial of Service (DoS) by sending crafted strings to endpoints utilizing Elysia's t.String({ format: 'url' }) schema validation.
A critical Regular Expression Denial of Service (ReDoS) vulnerability in the Elysia TypeScript framework allows unauthenticated remote attackers to cause severe CPU exhaustion. The flaw exists in the TypeBox-backed URL validation schema, affecting all versions prior to 1.4.26.
The vulnerability resides in the URL validation logic within Elysia's schema system, which utilizes TypeBox for input validation. The framework implements a global FormatRegistry to store regular expression patterns for common string formats, including URLs, emails, and UUIDs. When a developer defines a schema requiring URL validation via t.String({ format: 'url' }), the framework evaluates incoming data against the registered URL regular expression.
This validation process occurs synchronously on the main thread prior to executing the route handler. Due to an inefficient regular expression complexity flaw (CWE-1333) in the URL format pattern, the validation logic is susceptible to a Regular Expression Denial of Service (ReDoS) attack. Remote attackers can exploit this flaw to cause catastrophic backtracking in the regex engine, leading to severe CPU exhaustion.
The vulnerability affects all Elysia versions prior to 1.4.26. Because Node.js and Bun utilize a single-threaded event loop architecture, a blocked thread prevents the server from processing any subsequent requests. A single malicious request can render the application unresponsive, making this a highly effective Denial of Service vector.
The root cause of this vulnerability is catastrophic backtracking located in the user-info and hostname segments of the URL regular expression. The framework implemented an overly permissive pattern to validate the username:password@ section of a URL. The regex engine struggles to efficiently process strings that partially match this pattern but fail to complete it.
The specific vulnerable regex segment is (?:\S+(?::\S*)?@)?. In this pattern, the non-whitespace quantifier \S+ is greedy. It overlaps with the optional password component (?::\S*)?. Both segments attempt to consume the same non-whitespace characters from the input string.
When an input string contains a long sequence of non-whitespace characters but lacks the terminal @ character, the regex engine enters a state explosion. It attempts every possible permutation of dividing the input string between the initial greedy match and the optional secondary match. This results in exponential evaluation time relative to the input length.
The following diagram illustrates the backtracking execution path when the terminal character is absent:
The mitigation requires modifying the regular expression to ensure the match paths are mutually exclusive. The fix was introduced in commit d17a7aa204b5feea65d6d8f7651fb7141fb322bd, updating the FormatRegistry initialization logic for the URL pattern. The patch replaces the generic non-whitespace quantifiers with specific character classes.
The following code block demonstrates the difference between the vulnerable and patched regex segments:
// Vulnerable Regex Segment
const vulnerable = /(?:\S+(?::\S*)?@)?/;
// Patched Regex Segment
const patched = /(?:[^\s:@]+(?::[^\s@]*)?@)?/;The fixed version substitutes \S+ with [^\s:@]+ and \S* with [^\s@]*. By explicitly excluding the : and @ delimiters from the repeating groups, the regex engine is forced to fail linearly. When the engine encounters a sequence of characters without the required delimiters, it immediately halts the matching process for that segment.
This patch completely eliminates the exponential backtracking path. Benchmarks indicate that the validation time for a 32,768-character payload drops from approximately 34.6 seconds down to 3.05 milliseconds. The fix is comprehensive for this specific user-info segment overlap.
Exploitation requires no authentication and relies solely on sending a crafted HTTP request to an endpoint that validates URL parameters. An attacker constructs a payload consisting of a valid URL scheme followed by an exceptionally long string of non-whitespace characters. The payload must omit the @ symbol to trigger the backtracking loop.
A reliable proof-of-concept payload uses the structure 'http://a'.repeat(n). When n equals 32,768, the input length is sufficient to stall the event loop for over 30 seconds on standard hardware. The attacker packages this payload into a JSON body and transmits it via a standard POST request.
The following snippet demonstrates the exploitation methodology:
const n = 32768;
const payload = {
link: 'http://a'.repeat(n)
};
fetch('http://localhost:3000/validate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
});Public proof-of-concept code is available at https://github.com/EdamAme-x/elysia-poc-redos. Attackers utilizing this PoC can easily automate the transmission of multiple payloads. Sending concurrent malicious requests ensures the server remains perpetually locked, resulting in a sustained Denial of Service condition.
The vulnerability carries a CVSS v3.1 base score of 7.5, categorized as High severity. The vector string CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H reflects the network attack vector, low complexity, lack of required privileges, and the high impact on system availability.
Confidentiality and integrity are not impacted by this flaw. The attacker cannot execute arbitrary code, read sensitive memory, or modify system data. The sole consequence is the complete exhaustion of CPU resources, leading to an application hang.
Because the event loop is blocked synchronously, legitimate user requests queue indefinitely or time out. In cloud environments utilizing auto-scaling, this behavior can trigger unintended scaling events. The application instances will consume 100% CPU, potentially resulting in inflated infrastructure costs before the health checks eventually terminate the unresponsive containers.
The primary and most effective remediation is upgrading the Elysia framework to version 1.4.26 or later. This release contains the updated TypeBox FormatRegistry patterns that resolve the catastrophic backtracking flaw. Development teams should audit their package.json and lockfiles to ensure no transitive dependencies are locking Elysia to a vulnerable version.
If immediate patching is impossible, developers can mitigate the risk by enforcing strict length boundaries on string inputs. Setting a maxLength property on the schema definition bounds the maximum processing time. For example, restricting URLs to 288 characters prevents the regex engine from entering prolonged backtracking cycles.
Alternatively, developers can manually override the vulnerable regular expression within the FormatRegistry. By importing FormatRegistry from @sinclair/typebox, administrators can delete the existing url format and set a custom, safe regular expression pattern. This temporary workaround protects the application without requiring a framework version bump.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
elysia ElysiaJS | < 1.4.26 | 1.4.26 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-1333 |
| Attack Vector | Network |
| CVSS v3.1 Score | 7.5 (High) |
| Impact | Denial of Service (Availability: High) |
| Exploit Status | Proof-of-Concept Available |
| Affected Component | t.String({ format: 'url' }) |
The regular expression engine's complexity scales exponentially with the input size when encountering overlapping groups and lacking a terminal character.