{"id":"GHSA-4cwx-7wf7-3272","summary":"undici vulnerable to cross-user information disclosure and parse-time crash via degenerate private cache directives","details":"### 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).","aliases":["CVE-2026-13697"],"modified":"2026-08-03T19:30:08.032996821Z","published":"2026-08-03T19:19:47Z","database_specific":{"cwe_ids":["CWE-200","CWE-248","CWE-525"],"severity":"HIGH","github_reviewed":true,"github_reviewed_at":"2026-08-03T19:19:47Z","nvd_published_at":"2026-07-29T17:16:50Z"},"references":[{"type":"WEB","url":"https://github.com/nodejs/undici/security/advisories/GHSA-4cwx-7wf7-3272"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-13697"},{"type":"WEB","url":"https://github.com/nodejs/undici/commit/4fe5bc5fefe5ac81a200fc8e1cf84b8bf8464451"},{"type":"WEB","url":"https://cna.openjsf.org/security-advisories.html"},{"type":"PACKAGE","url":"https://github.com/nodejs/undici"},{"type":"WEB","url":"https://github.com/nodejs/undici/releases/tag/v7.29.0"},{"type":"WEB","url":"https://github.com/nodejs/undici/releases/tag/v8.9.0"}],"affected":[{"package":{"name":"undici","ecosystem":"npm","purl":"pkg:npm/undici"},"ranges":[{"type":"SEMVER","events":[{"introduced":"7.0.0"},{"fixed":"7.29.0"}]}],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/08/GHSA-4cwx-7wf7-3272/GHSA-4cwx-7wf7-3272.json"}},{"package":{"name":"undici","ecosystem":"npm","purl":"pkg:npm/undici"},"ranges":[{"type":"SEMVER","events":[{"introduced":"8.0.0"},{"fixed":"8.9.0"}]}],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/08/GHSA-4cwx-7wf7-3272/GHSA-4cwx-7wf7-3272.json"}}],"schema_version":"1.9.0","severity":[{"type":"CVSS_V3","score":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:H"}]}