A single crafted URL was enough to pin a Python process's CPU at 100% and take a service off the air — no authentication, no exploit chain, just a string passed into a library nearly every Python application depends on. CVE-2021-33503 is a Regular Expression Denial of Service (ReDoS) vulnerability in urllib3, one of the most widely used HTTP client libraries in the Python ecosystem, sitting underneath requests, pip, botocore, and countless internal tools. The flaw lives in urllib3's URL-parsing logic — specifically the regular expression used to split a URL into its authority component (the userinfo@host:port segment) — and it allows an attacker who controls a URL string passed to urllib3 to trigger catastrophic backtracking, consuming excessive CPU time and potentially causing a denial of service.
Because urllib3 is a transitive dependency of an enormous share of the Python package ecosystem, the practical blast radius of this CVE extends far beyond projects that import it directly. Any service that parses attacker-influenced URLs — redirect targets, webhook callback URLs, proxy configuration, SSRF-adjacent inputs, or even URLs embedded in uploaded files — was a candidate for exploitation if it ran a vulnerable urllib3 version.
Affected Versions and Components
- Component:
urllib3(Python HTTP client library) - Vulnerable versions: urllib3 releases prior to 1.26.5
- Fixed version: 1.26.5
- Root cause location: the URL-parsing regular expression in
urllib3/util/url.py, used to break a URL into scheme, authority, path, query, and fragment components - Weakness class: CWE-1333, Inefficient Regular Expression Complexity (ReDoS)
The defect is in how the authority portion of the URL — the section that can contain userinfo@host:port — is matched. A URL engineered with a long run of characters that are valid within that segment (for example, repeated @ or similarly structured tokens) can force the regex engine into exponential backtracking as it tries every possible way of splitting the string before failing or succeeding. The practical effect is that parsing a single, modestly sized malicious string can take seconds, minutes, or effectively "forever" on the CPU, well out of proportion to the size of the input.
Because any code path that calls into urllib3's URL normalization/parsing with attacker-influenced input is affected, the exposure isn't limited to obvious "HTTP client fetches a URL" scenarios. Applications that validate, canonicalize, or otherwise pass untrusted URL strings through urllib3's parsing utilities — even without making an outbound request — could be susceptible.
CVSS, EPSS, and KEV Context
CVE-2021-33503 was scored as a High-severity denial-of-service issue under CVSS v3.1, consistent with a network-exploitable flaw that requires no authentication or user interaction but is limited to an availability impact (no confidentiality or integrity loss) — the classic profile of a pure ReDoS bug (CVSS vector shape: network attack vector, low complexity, no privileges or user interaction required, unchanged scope, availability impact only).
From an exploitation-likelihood standpoint, this class of vulnerability tends to sit at the lower end of real-world weaponization: it requires the vulnerable application to route attacker-controlled strings into urllib3's URL parser, and the "exploit" itself is a crafted string rather than a memory-corruption payload, which limits its usefulness for anything beyond disruption. CVE-2021-33503 is not currently listed in CISA's Known Exploited Vulnerabilities (KEV) catalog, and it has not been associated with widespread in-the-wild exploitation campaigns. That said, absence from KEV doesn't mean the risk is zero — ReDoS bugs in ubiquitous parsing libraries are exactly the kind of "low and slow" resource-exhaustion primitive that shows up in targeted availability attacks against specific services, and they remain a favorite finding in bug bounty and pentest reports precisely because so many downstream applications never revisit pinned dependency versions.
Timeline
- Discovery and disclosure: The ReDoS was identified in urllib3's URL-authority-parsing regex and responsibly reported to the maintainers through the standard open-source disclosure process.
- Public advisory and patch: The urllib3 maintainers shipped version 1.26.5, which replaced the vulnerable regex-based parsing approach for the authority component with logic that eliminates the catastrophic-backtracking condition. A corresponding GitHub Security Advisory (GHSA-q2q7-5pp4-w6pg) and the CVE-2021-33503 record were published alongside the fix.
- Ecosystem propagation: As with most fixes to deeply transitive dependencies, the practical remediation timeline was longer than the patch timeline — downstream packages like
requests,botocore, and various SDKs needed to bump their pinned or minimum urllib3 versions before the fix reached the applications built on top of them, a pattern that played out over subsequent months as maintainers updated dependency constraints.
Remediation Steps
- Upgrade urllib3 to 1.26.5 or later. This is the definitive fix. Any 1.26.x release from 1.26.5 onward, as well as the later urllib3 2.x major line, contains the corrected parsing logic.
- Check transitive exposure, not just direct imports. Most organizations don't import urllib3 directly — it arrives via
requests,botocore/boto3,pipitself, and dozens of other packages. Run a dependency tree resolution (pip show,pipdeptree, or your SBOM tool of choice) to confirm the effective urllib3 version actually installed, not just what's declared in a top-level requirements file. - Re-pin and re-lock. If your project pins urllib3 (or a package that pins it) to an older version via
requirements.txt,Pipfile.lock,poetry.lock, or a vendored copy, update the pin and regenerate the lockfile — a patched version listed as "allowed" in a version range does nothing if the lockfile still resolves to a vulnerable build. - Audit container images and frozen artifacts. Base images, Lambda layers, and pre-built wheels can bake in an old urllib3 long after your source repository has been updated. Rebuild and redeploy rather than assuming a source-level fix has propagated.
- Validate and bound URL input where feasible. As defense in depth, enforce reasonable length limits and character-set validation on any URL strings sourced from untrusted input (redirect targets, webhook URLs, user-supplied links) before they're handed to any parsing library — this reduces exposure to ReDoS-class issues generally, including ones not yet discovered.
- Confirm the fix with a targeted test. After upgrading, verify that parsing a long, adversarial authority string (many repeated
@characters, for example) returns quickly rather than hanging, as part of your regression or security test suite.
How Safeguard Helps
CVE-2021-33503 is a textbook example of why supply chain visibility has to go deeper than a top-level requirements.txt file. urllib3 is rarely a direct dependency for most engineering teams — it's buried three or four layers down inside requests, cloud SDKs, and internal tooling, which means the question "are we affected?" can't be answered by reading a manifest. It has to be answered by resolving the actual dependency graph that ends up in production.
Safeguard's software composition analysis continuously inventories every direct and transitive dependency across your repositories, build artifacts, and deployed container images, so a finding like CVE-2021-33503 is mapped against what's actually installed, not just what's declared. When a vulnerable urllib3 version is present — whether pulled in by requests, botocore, or a vendored copy inside a container base image — Safeguard surfaces the exact package path, the affected services, and the minimum version bump required to close the gap.
Beyond detection, Safeguard prioritizes findings using the same signals covered above — CVSS severity, EPSS exploitation likelihood, and KEV status — so ReDoS-class findings like this one are triaged relative to their real-world risk rather than treated identically to a remote code execution bug. That means teams aren't asked to treat every dependency alert as a fire drill; instead, remediation work is ranked against actual exploitability and business impact, with clear guidance on which services need the urllib3 bump first and which can be batched into routine patch cycles.
Finally, because CVE-2021-33503's remediation often stalls at the "rebuild and redeploy" step — the source fix lands, but old images and frozen artifacts linger — Safeguard's continuous monitoring re-checks deployed artifacts over time, catching cases where a patch was merged upstream but never actually shipped to production. For software supply chain risks that hide in transitive dependencies and stale build artifacts, that continuous re-verification is often the difference between a vulnerability that's "fixed in the codebase" and one that's actually closed everywhere it runs.