All posts

Field guide

ReDoS in AI-generated code: when one string freezes your server

A regular expression that validates fine on normal input can take exponential time on a crafted one, and a single short request is enough to pin a CPU and stall your service. AI tools compose these patterns without reasoning about the matching engine's cost. Here is how to spot and fix a ReDoS.

Last updated

Regular expression denial of service, or ReDoS, is one of the less obvious ways AI-generated code can fail. A pattern that matches correctly and looks reasonable can, on the right input, send the regex engine into an exponential search that takes seconds or minutes to finish. On a normal server that stalls the worker for everything else, so a few crafted requests become an outage.

Why AI tools produce these patterns

An assistant builds a regex by composing pieces that look right, and nested quantifiers like (a+)+ or a repeated group over overlapping characters read as harmless syntax to a model that is not reasoning about time complexity. The pattern validates the example input it was given, so nothing flags the exponential edge case hiding inside it.

// nested quantifier: exponential on "aaaa...!" style input
const re = /^(a+)+$/;

// a real-world shape: a repeated group over overlapping chars
const emailish = /^(\w+\s*)*@example\.com$/;

The engine backtracks through the many ways those repeats could match input that ultimately fails, and the work grows explosively with length. The concept in full is in the broader family of volume-based attacks, with the specifics here being about the pattern itself.

Want to see exactly what Prbl flags? Watch it scan a demo app, no repo or account needed.

See a live scan →

The fix: remove the ambiguity

Rewrite the pattern so there is one clear way to match. Flatten nested quantifiers, avoid overlapping alternations, and anchor the expression. For structured formats, a purpose-built parser or a simple length cap before matching is safer than an elaborate regex.

// flatten the nesting; same language, no catastrophic backtracking
const re = /^a+$/;

// anchor and avoid the overlapping repeat
const emailish = /^\w+@example\.com$/;

Then confirm it: feed the pattern a long adversarial string with a timeout and check that matching time stays roughly linear. The full walkthrough is in the fix for catastrophic regex backtracking, and capping request work pairs well with rate limiting as a backstop.

Frequently asked questions

How can a regular expression cause a denial of service?

Certain patterns make the regex engine explore an exponential number of ways to match a string before giving up, which is called catastrophic backtracking. On a crafted input the engine can spend seconds or minutes on a single short string. On a typical event-loop server that one match blocks everything else on the worker, so a handful of crafted requests can take the whole service down with almost no bandwidth.

What does a vulnerable pattern look like?

The classic tell is a quantifier applied to a group that itself contains a quantifier over overlapping characters, like (a+)+ or (\w+\s*)*. Because the same input can be matched many different ways by the nested repeats, the engine tries all of them on input that ultimately fails to match. If you see a repeat wrapped around another repeat over similar characters, treat it as suspect.

How do I fix a ReDoS-prone regex?

Remove the ambiguity that causes the backtracking. Flatten nested quantifiers so there is one clear way to match, avoid overlapping alternations where a character can match multiple branches, and anchor the pattern. For structured formats, a real parser or a length cap is safer than an elaborate regex. Rewriting the pattern to be unambiguous keeps its time linear in the input length.

How do I know if a pattern is actually vulnerable?

Test it. Feed the suspect regex a long adversarial string, for example many repeated characters followed by one that breaks the match, and run it with a timeout. If matching time grows sharply as the input lengthens, the pattern backtracks catastrophically. A safe pattern stays roughly linear. Automated tools can also analyze a regex for known dangerous shapes.

Check your patterns

Dangerous regex shapes are recognizable, and a scan flags a pattern with nested or overlapping quantifiers so you can rewrite it before someone sends the input that triggers the blowup. Run a free scan and see whether any regex in your app can be forced to backtrack.

Prbl scans your live app or your codebase for exactly the kinds of issues above.

ReDoS in AI-Generated Code: When One String Freezes Your Server: Prbl