Babel helps developers use cutting-edge JavaScript—years before browsers understand it—by compiling new features to older code. However, in versions of Babel before 7.26.10 and 8..-alpha.17, a subtle but serious bug crept in: compiling code with *named capture groups* in regular expressions, Babel generates a .replace polyfill which can slow down your app drastically—possibly letting attackers bog down your server or app with little effort. This is tracked as CVE-2025-27789.

Read on for a beginner-friendly breakdown, actual code snippets, links to the original sources, and what you should do to stay safe.

What Is A Named Capture Group? Why Is This Interesting?

A *named capture group* makes regex code more readable and easier to maintain. Here’s a quick example:

// Named group "name"
let re = /Hello, (?<name>\w+)!/g;
let str = "Hello, Bob! Hello, Alice!";

// Extracts: name: "Bob", name: "Alice"
str.replace(re, (match, ...args) => {
  let groups = args.pop();
  return Hi ${groups.name}!;
});

Babel adds compatibility for environments that don’t support this feature by transforming (or *polyfilling*) your code. But if you compile code with named capture groups and later call .replace using *untrusted* user data for the replacement pattern, Babel’s polyfill gets bogged down: It processes the string in quadratic time.

So, What’s the Problem with Babel’s .replace Polyfill?

The generated code for named pattern groups uses a polyfilled .replace method. For certain malicious replacement strings—especially those provided by users—this code runs much slower than expected. Because of how the polyfill looks up and replaces named groups, it can slow down (“quadratic complexity”) as the replacement string grows, causing timeouts or resource exhaustion.

If an attacker can supply the replacement pattern string as input, they can freeze your app for a long time or cause a denial-of-service.

When Am I Vulnerable?

You are at risk if all of these conditions are true:

1. You use Babel (before 7.26.10 or 8..-alpha.17) to compile code with regex named capturing groups.

You use the .replace method with regexes containing named groups.

3. Untrusted data (for instance: user input) is used as the replacement string argument to .replace.

Here’s a minimal example showing how Babel compiles such code (simplified for readability)

// Modern JS
const regex = /(?<word>\w+)/g;
const input = "test test test";
const userInput = "$<verylongnamename>"; // Attacker-controlled
const result = input.replace(regex, userInput);

// Compiled by Babel <7.26.10 output (simplified)
function replacePolyfill(str, replacer) {
  // Naive loop through string chars and patterns
  // Each character processed against the replacement string!
  // Quadratic O(N^2) behavior
}

With attacker-supplied input like

'$<verylongnamename>$<verylongnamename>$<verylongnamename>...repeat a lot...'

the .replace polyfill can take seconds or minutes, depending on string size. That’s the performance trap!

Real-World Impact Example

Let’s say you run a Node.js web server that processes form data and logs results. If you take user input to format log messages (don’t do this!) and run it through a regex with named groups compiled by an outdated Babel version, one user could submit a 10,000-character replacement pattern and the server might hang, affecting everyone.

1. Upgrade Babel and Helpers!

- Update @babel/helpers and @babel/runtime to 7.26.10 (or 8..-alpha.17 for alpha users).
- Most users depend on @babel/core which will pull helpers; upgrading @babel/core to 7.26.10 guarantees a safe version.

Recompile your code after upgrading!

2. You MUST recompile!
Simply updating your node_modules is not enough; re-run your build (e.g., npm run build, webpack, etc) to regenerate fixed output.

3. Avoid passing untrusted user input as the replacement string to .replace on regexes with named groups in any code which Babel might have polyfilled.

No Workarounds

There are no known workarounds. You must upgrade and recompile to be safe.

References

- Github Security Advisory
- Babel Changelog (7.26.10)
- NIST/NVD Entry for CVE-2025-27789 (when available)

[ ] Is your project using Babel (before 7.26.10 or 8..-alpha.17)?

- [ ] Do you use regexes with named capturing groups and pass .replace a string that could be user-supplied?
- [ ] If yes: Update your Babel helpers/runtime/core, and re-run your code through Babel to recompile everything!

Timeline

Published on: 03/11/2025 20:15:18 UTC