{"id":"CVE-2026-120415","kind":"vulnerability","aliases":["CVE-2026-120415"],"related":[],"title":"undici: array-form headers leak credentials on cross-origin redirects","description":"undici is an HTTP client for Node.js. In versions 7.0.0 through 7.30.1 and 8.0.0 through 8.12.3, the redirect interceptor strips sensitive headers such as Authorization, Cookie, Proxy-Authorization, and Host when a request is redirected to a different origin, but when request headers are supplied as an array of name and value tuples (a valid documented input, for example from Object.entries), the redirect handler misreads them as a flat list so the header names never match and the sensitive headers are not removed. If a header-normalizing interceptor such as cache or deduplicate is composed outside the redirect interceptor, it then serializes the retained headers onto the cross-origin request, disclosing the caller's origin-bound credentials to the unrelated redirect destination. This is a representation-dependent bypass of the cross-origin header stripping added in CVE-2024-30260. The issue is fixed in undici 7.30.2 and 8.12.4, and users should upgrade to one of those versions or later. As a workaround, supply request headers as a plain object or a flat name and value array rather than an array of tuples, or compose the redirect interceptor outside the normalizing interceptor.","summary":"undici, the HTTP client built into Node.js, fails to strip Authorization and Cookie headers on cross-origin redirects when headers are passed as an array of tuples. When a cache or deduplicate interceptor sits outside the redirect interceptor, those credentials are sent to the redirect destination.","severity":"medium","cvss":5.9,"epss":null,"exploited":false,"exploited_at":null,"products":[],"ecosystems":[],"tags":["http-client","node.js","package","undici"],"not_affected_if":["flat-header-array","plain-object-headers","redirect-interceptor-outermost"],"how_to_check":"- Run `npm ls undici` to find undici versions in the project tree\n- Look for undici `7.0.0` through `7.30.1` or `8.0.0` through `8.12.3`\n- Check whether code passes request headers as an array of tuples (for example from Object.entries) and composes the cache or deduplicate interceptor outside the redirect interceptor","fix":"- undici `7.30.2`\n- undici `8.12.4`","status":"open","published_at":"2026-11-06T10:16:36+00:00","first_seen_at":"2026-11-06T10:40:56+00:00","triaged_at":"2026-11-06T10:41:21+00:00","updated_at":"2026-11-06T10:41:21+00:00","category":"package","confidence":0.8,"triage":{"at":"2026-11-06T10:41:21Z","model":"claude-haiku-5-5","output":{"fix":"- undici `7.30.2`\n- undici `8.12.4`","reach":"internet","title":"undici: array-form headers leak credentials on cross-origin redirects","impact":"medium","summary":"undici, the HTTP client built into Node.js, fails to strip Authorization and Cookie headers on cross-origin redirects when headers are passed as an array of tuples. When a cache or deduplicate interceptor sits outside the redirect interceptor, those credentials are sent to the redirect destination.","audience":"developers","category":"package","nicknames":[],"who_cares":["node.js","undici","http-client"],"confidence":0.8,"fix_status":"available","needs_auth":"no","worst_case":"caller's credentials sent to an unrelated redirect destination","analyst_note":"","how_to_check":"- Run `npm ls undici` to find undici versions in the project tree\n- Look for undici `7.0.0` through `7.30.1` or `8.0.0` through `8.12.3`\n- Check whether code passes request headers as an array of tuples (for example from Object.entries) and composes the cache or deduplicate interceptor outside the redirect interceptor","plain_action":"","needs_analyst":false,"not_affected_if":["plain-object-headers","flat-header-array","redirect-interceptor-outermost"],"who_is_affected":"Applications that use undici's request API with header arrays of name and value tuples, and that follow redirects with the cache or deduplicate interceptor composed outside the redirect interceptor. Code that passes headers as a plain object or a flat array, or that composes the redirect interceptor outside the normalizing interceptor, is not exposed.","user_interaction":"no","needs_special_setup":"yes","severity_if_unknown":"unknown"},"cost_usd":0.000751,"input_tokens":4507,"output_tokens":601,"severity_before":"medium"},"analyst_status":null,"analyst_note":null,"search":"'-120415':15A,18A '-2024':215C '-2026':14A,17A '-30260':216C '7.0.0':81C '7.30.1':83C '7.30.2':223C '8.0.0':85C '8.12.3':87C '8.12.4':225C 'add':212C 'array':3A,50B,120C,253C,257C 'array-form':2A 'author':35B,96C,100C 'bound':191C 'built':29B 'bypass':204C 'cach':55B,164C 'caller':187C 'client':21B,28B,76C 'compos':168C,261C 'cooki':37B,97C 'credenti':7A,65B,192C 'cross':10A,41B,182C,208C 'cross-origin':9A,40B,181C,207C 'cve':13A,16A,214C 'dedupl':57B,166C 'depend':203C 'destin':71B,197C 'differ':110C 'disclos':185C 'document':128C 'exampl':131C 'fail':32B 'fix':220C 'flat':141C,249C 'form':4A 'handler':136C 'header':5A,38B,45B,93C,115C,145C,152C,159C,178C,210C,242C 'header-norm':158C 'host':102C 'http':20B,27B,75C 'http-client':19B 'input':129C 'interceptor':58B,63B,90C,161C,172C,264C,268C 'issu':218C 'later':236C 'leak':6A 'list':142C 'match':148C 'misread':137C 'name':122C,146C,250C 'never':147C 'node.js':22B,31B,78C 'normal':160C,267C 'object':246C 'object.entries':133C 'one':231C 'onto':179C 'origin':11A,42B,111C,183C,190C,209C 'origin-bound':189C 'outsid':60B,169C,265C 'packag':23B 'pass':47B 'plain':245C 'proxi':99C 'proxy-author':98C 'rather':254C 'redirect':12A,43B,62B,70B,89C,107C,135C,171C,196C,263C 'remov':155C 'represent':202C 'representation-depend':201C 'request':105C,114C,184C,241C 'retain':177C 'sensit':92C,151C 'sent':67B 'serial':175C 'sit':59B 'strip':34B,91C,211C 'suppli':117C,240C 'tupl':52B,125C,259C 'undici':1A,24B,25B,72C,222C 'unrel':195C 'upgrad':229C 'user':227C 'valid':127C 'valu':124C,252C 'version':80C,234C 'workaround':239C","nicknames":[],"mitigations":[],"who_affected":"Applications that use undici's request API with header arrays of name and value tuples, and that follow redirects with the cache or deduplicate interceptor composed outside the redirect interceptor. Code that passes headers as a plain object or a flat array, or that composes the redirect interceptor outside the normalizing interceptor, is not exposed.","tier":"C","verified":{},"analyst_revisit_at":null,"fix_status":"available","audience":"developers","plain_action":null,"pkeys":[],"ptokens":[],"labels":["httpclient","medium","nodejs","package","undici"],"campaign_type":null,"search_a":"'-120415':15A,18A '-2026':14A,17A 'array':3A 'array-form':2A 'credenti':7A 'cross':10A 'cross-origin':9A 'cve':13A,16A 'form':4A 'header':5A 'leak':6A 'origin':11A 'redirect':12A 'undici':1A","search_b":"'array':50B 'author':35B 'built':29B 'cach':55B 'client':21B,28B 'cooki':37B 'credenti':65B 'cross':41B 'cross-origin':40B 'dedupl':57B 'destin':71B 'fail':32B 'header':38B,45B 'http':20B,27B 'http-client':19B 'interceptor':58B,63B 'node.js':22B,31B 'origin':42B 'outsid':60B 'packag':23B 'pass':47B 'redirect':43B,62B,70B 'sent':67B 'sit':59B 'strip':34B 'tupl':52B 'undici':24B,25B","search_c":"'-2024':215C '-30260':216C '7.0.0':81C '7.30.1':83C '7.30.2':223C '8.0.0':85C '8.12.3':87C '8.12.4':225C 'add':212C 'array':120C,253C,257C 'author':96C,100C 'bound':191C 'bypass':204C 'cach':164C 'caller':187C 'client':76C 'compos':168C,261C 'cooki':97C 'credenti':192C 'cross':182C,208C 'cross-origin':181C,207C 'cve':214C 'dedupl':166C 'depend':203C 'destin':197C 'differ':110C 'disclos':185C 'document':128C 'exampl':131C 'fix':220C 'flat':141C,249C 'handler':136C 'header':93C,115C,145C,152C,159C,178C,210C,242C 'header-norm':158C 'host':102C 'http':75C 'input':129C 'interceptor':90C,161C,172C,264C,268C 'issu':218C 'later':236C 'list':142C 'match':148C 'misread':137C 'name':122C,146C,250C 'never':147C 'node.js':78C 'normal':160C,267C 'object':246C 'object.entries':133C 'one':231C 'onto':179C 'origin':111C,183C,190C,209C 'origin-bound':189C 'outsid':169C,265C 'plain':245C 'proxi':99C 'proxy-author':98C 'rather':254C 'redirect':89C,107C,135C,171C,196C,263C 'remov':155C 'represent':202C 'representation-depend':201C 'request':105C,114C,184C,241C 'retain':177C 'sensit':92C,151C 'serial':175C 'strip':91C,211C 'suppli':117C,240C 'tupl':125C,259C 'undici':72C,222C 'unrel':195C 'upgrad':229C 'user':227C 'valid':127C 'valu':124C,252C 'version':80C,234C 'workaround':239C","first_public_at":"2026-11-05T10:28:01+00:00","kev":null,"cvss_vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N","cvss_by":"ce714d77-add3-4f53-aff5-83d477b104bb","poc_count":0,"sources":[{"source":"nvd","external_id":"CVE-2026-120415","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-120415","severity":null,"published_at":"2026-11-06T10:16:36+00:00","modified_at":"2026-11-06T10:16:36+00:00","first_seen_at":"2026-11-06T10:40:56+00:00","fetched_at":"2026-11-06T10:40:56+00:00","note":null}],"documents":[{"id":85512,"url":"https://github.com/nodejs/undici/security/advisories/GHSA-9v6h-8rgp-m69f","title":"Vendor advisory: github.com","kind":"vendor","source":"nvd","publisher":"vendor","text":null,"published_at":"2026-11-05T10:28:01+00:00","relation":"advisory","confidence":null,"note":"Vendor advisory: github.com"}],"exploit_sources":[],"notice":"Free to read, with fair use of about 60 pages a minute. For higher limits or API access: sales@infrastack.ai"}