A regular expression denial-of-service (ReDoS) flaw in http-cache-semantics, a widely used npm library for interpreting HTTP caching headers, can let a malicious or compromised HTTP server (or a man-in-the-middle attacker) hang a consuming Node.js process by returning a crafted Cache-Control header. Tracked as CVE-2022-25881 (GHSA-rc47-6667-2j5j), the bug lives in the library's parseCacheControl function and affects every version prior to 4.1.1. Because http-cache-semantics is a deep, often invisible dependency of tools like make-fetch-happen, cacheable-request, and by extension large parts of the npm tooling and Node HTTP-caching ecosystem, the practical blast radius is much larger than the package's modest download numbers on its own would suggest — this is exactly the kind of transitive risk that shows up in an SBOM but rarely gets prioritized until it's exploited.
What is http-cache-semantics?
http-cache-semantics implements RFC 7234 HTTP caching rules in JavaScript: given a request and response pair, it tells a caching layer whether a response is cacheable, for how long, and whether a cached copy can be reused for a subsequent request. It doesn't perform network I/O itself — it's a pure logic library that other packages embed to build HTTP caches, proxies, and fetch wrappers. That "boring utility" profile is precisely why it ended up nested many layers deep in dependency trees: package managers, build tools, and HTTP clients pull it in indirectly through packages such as make-fetch-happen (used by npm itself), cacheable-request, and various proxy/caching middlewares, without the top-level application ever declaring it directly.
The Vulnerability
The parseCacheControl function tokenizes the Cache-Control header value using a regular expression that, under certain crafted inputs, exhibits catastrophic backtracking. An attacker who controls (or can influence) the HTTP response — a malicious upstream server, a compromised CDN edge, or an attacker positioned to inject headers — can supply a specially constructed Cache-Control string that causes the regex engine to spend an amount of time exponential in the length of the malicious substring. On a single-threaded Node.js event loop, that translates directly into the process hanging: no other requests are served, health checks time out, and the application effectively suffers a denial of service until the call returns or the process is killed.
This is a classic ReDoS pattern: no memory corruption, no code execution, just an algorithmic trapdoor in input parsing that turns "parse this header" into "burn 100% CPU indefinitely." The trigger is server-side response parsing rather than user-supplied request data, which narrows the practical attack surface to scenarios where the vulnerable application fetches content from, or caches responses served by, an untrusted or attacker-influenced origin — think package registries, proxy servers, web scrapers, and any service that caches responses from third-party or federated endpoints.
Affected Versions and Components
- Package:
http-cache-semantics(npm) - Affected: versions prior to 4.1.1
- Fixed in: 4.1.1
- Advisory: GHSA-rc47-6667-2j5j / CVE-2022-25881
- Common transitive paths:
make-fetch-happen→http-cache-semantics;cacheable-request→http-cache-semantics; and any HTTP caching/proxy middleware built on these. Becausemake-fetch-happenis used by npm's own dependency-fetching machinery in older releases, this CVE also surfaced discussion about Node.js tooling supply-chain hygiene, not just application-level exposure.
If your organization runs Node.js services that make outbound HTTP requests through a caching fetch wrapper, use an internal npm mirror/proxy, or build CDN/edge caching logic on top of common JavaScript HTTP libraries, there's a reasonable chance this package is present several levels down in your node_modules tree even though nothing in your own package.json mentions it by name.
CVSS, EPSS, and KEV Context
- CVSS v3.1: 7.5 (High) — vector
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H, reflecting a network-exploitable, low-complexity, no-privileges-required issue whose only impact is availability. There is no confidentiality or integrity impact — this is purely a service-disruption bug. - EPSS: Exploit prediction scores for this CVE have historically sat in the low range. ReDoS bugs in parsing libraries are common findings that rarely see mass, automated internet-wide exploitation, since triggering them typically requires the attacker to control or influence a specific response an application chooses to fetch or cache — a more targeted condition than, say, an unauthenticated RCE.
- CISA KEV: As of this writing, CVE-2022-25881 does not appear on CISA's Known Exploited Vulnerabilities catalog. That should not be read as "safe to ignore" — KEV absence mainly means no confirmed in-the-wild mass exploitation has been publicly attributed to it, not that abuse is impossible for a targeted actor who wants to knock out a specific caching tier or CI pipeline.
In short: high severity on the CVSS scale because a successful trigger fully denies availability, but a lower observed likelihood of opportunistic exploitation because the attacker generally needs some control over the response side of the HTTP exchange.
Timeline
- Prior to 2022:
http-cache-semanticsships with aparseCacheControlregex containing the vulnerable backtracking pattern across its 4.0.x/4.1.0 line and earlier. - March 2022: The ReDoS behavior is publicly disclosed and assigned CVE-2022-25881; a GitHub Security Advisory (GHSA-rc47-6667-2j5j) is published detailing the flaw in
parseCacheControl. - March 2022: Maintainers ship v4.1.1, replacing the vulnerable regex logic to eliminate the catastrophic backtracking path.
- 2022 onward: Downstream consumers —
make-fetch-happen,cacheable-request, and packages built on top of them — release updates pinning or requiring the patchedhttp-cache-semantics, gradually propagating the fix through the dependency graph. Because the fix sits several layers deep, propagation lag varies significantly: applications pinned to older lockfiles, vendored dependency snapshots, or outdated versions of npm tooling itself can remain exposed long after the upstream patch ships.
Remediation Steps
- Identify exposure across your dependency graph, not just direct dependencies. Run
npm ls http-cache-semantics(or the Yarn/pnpm equivalent) across every service and build tool, including internal tooling and CI images, since this package is almost always pulled in transitively. - Upgrade to 4.1.1 or later. If it's a direct dependency, bump the version constraint. If it's transitive, upgrade the intermediate package (
make-fetch-happen,cacheable-request, etc.) to a version that requires the patched release, or use your package manager's override/resolution mechanism (overridesin npm,resolutionsin Yarn,pnpm.overrides) to force the patched version when the parent package hasn't bumped its range yet. - Regenerate and commit updated lockfiles. A version bump in
package.jsonalone doesn't help ifpackage-lock.json/yarn.lock/pnpm-lock.yamlstill resolve to a vulnerable version — verify the lockfile actually pins ≥4.1.1 after upgrading. - Rebuild and redeploy affected build/CI images. Since npm tooling itself has depended on this package transitively in some versions, don't limit remediation to application containers — check CI runners, base images, and internal registry proxies that perform HTTP caching.
- Add a regression gate. Wire dependency scanning into CI (
npm audit, or your SCA/SBOM tool of choice) so a reintroduction of a vulnerable transitive version fails the build automatically, rather than being caught weeks later in a periodic scan. - If you can't patch immediately, reduce exposure. Apply request/response size limits and timeouts around any HTTP client path that touches
Cache-Controlparsing from untrusted origins, and consider circuit-breaking or worker-pool isolation so a single hung parse doesn't take down an entire service's event loop.
How Safeguard Helps
Safeguard's SBOM ingestion continuously maps exactly where packages like http-cache-semantics live in your dependency graph — including four and five layers deep behind make-fetch-happen or cacheable-request — so you're not relying on manual npm ls audits across dozens of repos to find every instance. Griffin AI, Safeguard's reasoning engine, performs reachability analysis to determine whether your application code actually exercises the vulnerable parseCacheControl path on attacker-influenceable input, letting your team separate "technically present in the tree" from "actually exploitable in this service" and prioritize accordingly. For confirmed exposures, Safeguard generates auto-fix pull requests that bump the vulnerable transitive dependency and regenerate lockfiles correctly, cutting remediation from a multi-repo manual chore down to a review-and-merge. And because Safeguard tracks CVSS, EPSS, and KEV signals alongside your own reachability context, CVE-2022-25881 and issues like it get triaged by real risk to your environment rather than by CVSS score alone — the same approach we bring to bear across the broader software supply chain, competitive with what teams expect from Snyk, Wiz, or Aqua.