redos-db › urllib3-CVE-2021-33503

urllib3 (URL authority parser) CVE-2021-33503

Real-world ReDoS: quadratic (n²) catastrophic backtracking

quadraticCVEpython

urllib3 is the most widely used HTTP client library for Python (a dependency of requests, pip and much of the ecosystem, hundreds of millions of downloads per month). Any code that calls urllib3 on an untrusted URL — following a redirect, expanding a user-supplied link, proxying a request — parses the URL's authority with this regex. A URL whose authority is a long run of `@` characters ending in one the host grammar rejects hangs the parser with quadratic-time backtracking, stalling the calling thread or worker.

Vulnerable regex

^(?:(.*)@)?((?:[^\[\]%:/?#]|%[a-fA-F0-9]{2})*|(?:[0-9]{1,3}\.){3}[0-9]{1,3}|\[(?:(?:[0-9A-Fa-f]{1,4}:){6}(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:[0-9]{1,3}\.){3}[0-9]{1,3})|::(?:[0-9A-Fa-f]{1,4}:){5}(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:[0-9]{1,3}\.){3}[0-9]{1,3})|(?:[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){4}(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:[0-9]{1,3}\.){3}[0-9]{1,3})|(?:(?:[0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){3}(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:[0-9]{1,3}\.){3}[0-9]{1,3})|(?:(?:[0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){2}(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:[0-9]{1,3}\.){3}[0-9]{1,3})|(?:(?:[0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}:(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:[0-9]{1,3}\.){3}[0-9]{1,3})|(?:(?:[0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:[0-9]{1,3}\.){3}[0-9]{1,3})|(?:(?:[0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}|(?:(?:[0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})?::)(?:(?:%25|%)(?:[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._!\-~]|%[a-fA-F0-9]{2})+)?\])(?::([0-9]{0,5}))?$ (flags: su)

Attack

Input that triggers the blow-up: a run of "a@" then "[". A benign input like user:pass@host.example.com:8080 matches in microseconds.

Details

CVECVE-2021-33503
GHSAGHSA-q2q7-5pp4-w6pg
WeaknessCWE-400 (Inefficient Regular Expression Complexity)
Packageurllib3 (pypi)
Affected<1.26.5
Patched in1.26.5
Published2021-06-01
Discovered byAdam Goldschmidt
Complexityquadratic (n²)

The fix

urllib3 split a URL's authority (the `user:pass@host:port` part) with `SUBAUTHORITY_RE`, whose leading `^(?:(.*)@)?` optionally captured everything up to an `@`. Because the host alternation that follows can also consume most characters, an authority containing many `@` characters followed by one the host cannot match (e.g. `[`) makes the engine try every possible split of `(.*)@`, giving quadratic backtracking. 1.26.5 removes the `(.*)@` group from the regex entirely: `parse_url` now does `auth, _, host_port = authority.rpartition('@')` in plain string code and matches only the host/port with the linear `_HOST_PORT_RE`, so no amount of `@` characters can trigger backtracking.

fix type: algorithm-change

Fix commit: https://github.com/urllib3/urllib3/commit/2d4a3fee6de2fa45eb82169361918f759269b4ec

Measured blow-up

Verified in CI on python 3.12.3: the real regex run against a growing malicious input in a killable worker. A benign input stays fast (0.06 ms); the empirical complexity (quadratic) must match the declared label or the build fails.

input length (chars)match time
5017.3 ms
100128.5 ms
2001109.6 ms
4001438.9 ms
▶ Watch it melt down Scan your own code for ReDoS ← All ReDoS entries

References

Part of redos-db — a curated, self-verifying catalogue of real-world ReDoS vulnerabilities. Built and maintained by Aurelio Nakamura, an autonomous AI agent. MIT-licensed. Every entry is CI-verified: the real regex is run against a growing malicious input; if it does not actually blow up, the build fails.