Skip to content

undici vulnerable to cross-user information disclosure and parse-time crash via degenerate private cache directives

High severity GitHub Reviewed Published Jul 29, 2026 in nodejs/undici • Updated Aug 3, 2026

Package

npm undici (npm)

Affected versions

>= 7.0.0, < 7.29.0
>= 8.0.0, < 8.9.0

Patched versions

7.29.0
8.9.0

Description

Summary

Two issues in undici's cache interceptor, both fixed by the same patch on lib/util/cache.js:

  1. Shared-cache disclosure: Responses with malformed qualified Cache-Control: private directives such as private="" or private="," can be incorrectly stored in the default shared cache, then served to a later caller with the same cache key.
  2. Parse-time crash: Mixed unqualified-and-qualified private directives in the same header (such as public, max-age=60, private, private="hdr") cause an uncaught TypeError in the cache-control parser, terminating the request.

Impact

Shared-cache disclosure

Applications using interceptors.cache() in shared mode may cache a user-specific response and serve it to a later caller with the same cache key. This can disclose private response bodies and headers, including Set-Cookie.

Required conditions:

  • the cache interceptor is enabled in shared mode, including the default configuration;
  • an upstream returns a malformed directive such as Cache-Control: public, max-age=300, private="";
  • another request later matches the same cache key, without a separating Vary header.

Parse-time crash

Applications using interceptors.cache() against an upstream that returns a Cache-Control header combining unqualified private with qualified private="..." see an uncaught TypeError: output.private.concat is not a function during response handling. The request rejects; depending on the consumer's error handling, the process may exit.

Details

private="" is parsed as { private: [''] }. The shared-cache guard only rejects private === true, so the response can be stored. When served from cache, the previous user's body and headers may be returned to a different user.

For the crash variant, an unqualified private directive sets output.private = true, then a subsequent qualified private="hdr" directive attempts output.private.concat(['hdr']), which throws because boolean has no concat method.

The patch routes the qualified-directive path through a shared helper that normalizes empty-after-trim arrays to true and preserves existing true values, closing both vectors.

Patches

Upgrade to undici 7.29.0 or 8.9.0. Both releases fix the qualified private directive handling that caused the shared-cache storage and the parser crash.

Workarounds

Until patched, avoid shared interceptors.cache() for user-specific responses, use type: 'private', or disable caching for affected origins.

Credit

Disclosure variant reported by @h0rk1p via HackerOne report #3817497.

References

@mcollina mcollina published to nodejs/undici Jul 29, 2026
Published by the National Vulnerability Database Jul 29, 2026
Published to the GitHub Advisory Database Aug 3, 2026
Reviewed Aug 3, 2026
Last updated Aug 3, 2026

Severity

High

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Network
Attack complexity
High
Privileges required
None
User interaction
None
Scope
Unchanged
Confidentiality
High
Integrity
None
Availability
High

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:H

EPSS score

Exploit Prediction Scoring System (EPSS)

This score estimates the probability of this vulnerability being exploited within the next 30 days. Data provided by FIRST.
(25th percentile)

Weaknesses

Exposure of Sensitive Information to an Unauthorized Actor

The product exposes sensitive information to an actor that is not explicitly authorized to have access to that information. Learn more on MITRE.

Uncaught Exception

An exception is thrown from a function, but it is not caught. Learn more on MITRE.

Use of Web Browser Cache Containing Sensitive Information

The web application does not use an appropriate caching policy that specifies the extent to which each web page and associated form fields should be cached. Learn more on MITRE.

CVE ID

CVE-2026-13697

GHSA ID

GHSA-4cwx-7wf7-3272

Source code

Credits

Loading Checking history
See something to contribute? Suggest improvements for this vulnerability.