{"id":"CVE-2026-13697","aliases":["GHSA-4cwx-7wf7-3272"],"title":"undici vulnerable to cross-user information disclosure and parse-time crash via degenerate private cache directives","summary":"undici vulnerable to cross-user information disclosure and parse-time crash via degenerate private cache directives","severity":"high","cvss":7.4,"cwe":["CWE-200","CWE-248","CWE-525"],"vendor":"undici","product":"undici","ecosystem":"npm","affected":["undici >= 7.0.0, < 7.29.0","undici >= 8.0.0, < 8.9.0"],"patched":["undici 7.29.0","undici 8.9.0"],"published":"2026-08-03","updated":"2026-08-03","source":"GHSA","sourceUrl":"https://github.com/advisories/GHSA-4cwx-7wf7-3272","references":[{"url":"https://github.com/nodejs/undici/security/advisories/GHSA-4cwx-7wf7-3272"},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-13697"},{"url":"https://github.com/nodejs/undici/commit/4fe5bc5fefe5ac81a200fc8e1cf84b8bf8464451"},{"url":"https://cna.openjsf.org/security-advisories.html"},{"url":"https://github.com/nodejs/undici/releases/tag/v7.29.0"},{"url":"https://github.com/nodejs/undici/releases/tag/v8.9.0"},{"url":"https://github.com/advisories/GHSA-4cwx-7wf7-3272"}],"tags":["ghsa","npm"],"epss":0.00463,"epssPercentile":0.39261,"ingestedAt":"2026-08-03T19:29:00.316Z","slug":"CVE-2026-13697","body":"## Overview\n\n### Summary\n\nTwo issues in undici's cache interceptor, both fixed by the same patch on `lib/util/cache.js`:\n\n1. **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.\n2. **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.\n\n### Impact\n\n#### Shared-cache disclosure\n\nApplications 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`.\n\nRequired conditions:\n\n- the cache interceptor is enabled in shared mode, including the default configuration;\n- an upstream returns a malformed directive such as `Cache-Control: public, max-age=300, private=\"\"`;\n- another request later matches the same cache key, without a separating `Vary` header.\n\n#### Parse-time crash\n\nApplications 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.\n\n### Details\n\n`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.\n\nFor 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.\n\nThe 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.\n\n### Patches\n\nUpgrade 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.\n\n### Workarounds\n\nUntil patched, avoid shared `interceptors.cache()` for user-specific responses, use `type: 'private'`, or disable caching for affected origins.\n\n### Credit\n\nDisclosure variant reported by @h0rk1p via HackerOne report [#3817497](https://hackerone.com/reports/3817497).\n\n## Affected packages\n\n- `undici >= 7.0.0, < 7.29.0`\n- `undici >= 8.0.0, < 8.9.0`\n\n## Remediation\n\nUpgrade to a patched release:\n\n- `undici 7.29.0`\n- `undici 8.9.0`","depth":"twilight","depthScore":41,"depthScoreParts":{"impact":40.7,"likelihood":0.1,"exploitation":0,"ransomware":0},"changes":[]}