{"id":"CVE-2026-87018","kind":"vulnerability","aliases":["CVE-2026-87018","GHSA-qrxm-fqhp-jwvm"],"related":[],"title":"undici vulnerable to Denial of Service via TLS 1.2 certificate-changing renegotiation","description":"## Impact\n\nundici crashes the client process when a TLS 1.2 server renegotiates after the connection is established and presents a different, CA-trusted certificate whose hostname does not match the requested host. Node.js re-runs hostname verification on the renegotiated handshake and destroys the socket with `ERR_TLS_CERT_ALTNAME_INVALID`. undici's established socket error handler asserted that this error code could never occur, so the peer-controlled error became an uncaught `AssertionError` that terminates the Node.js process. Both the HTTP/1.1 and HTTP/2 paths are affected.\n\nA malicious or compromised HTTPS endpoint reached through undici or the global `fetch()` can crash the client with a single server-initiated renegotiation, taking down all in-flight requests and background work in the process. Only TLS 1.2 is affected, because TLS 1.3 does not support renegotiation. Exploitation does not require a CA compromise: the attacker controls the endpoint and can present two ordinary valid certificates, the first matching the requested URL and the second intentionally not matching it.\n\n## Patches\n\nUpgrade to undici 6.29.1, 7.30.1, or 8.12.2.\n\n## Workarounds\n\nRestrict outbound connections to TLS 1.3, for example by setting `connect: { minVersion: 'TLSv1.3', maxVersion: 'TLSv1.3' }` on the client or agent, so that renegotiation cannot occur, when the target endpoints support TLS 1.3.","summary":"undici, the HTTP client behind Node's global fetch, crashes the whole Node.js process when a TLS 1.2 server renegotiates the connection and presents a certificate whose hostname does not match. An attacker who controls or can impersonate the HTTPS endpoint can take down all in-flight requests and background work with one renegotiation.","severity":"high","cvss":7.5,"epss":0.00187,"exploited":false,"exploited_at":null,"products":[{"name":"undici","fixed":["6.29.1"],"affected":">= 4.2.1, < 6.29.1","ecosystem":"npm"},{"name":"undici","fixed":["7.30.1"],"affected":">= 7.0.0, < 7.30.1","ecosystem":"npm"},{"name":"undici","fixed":["8.12.2"],"affected":">= 8.0.0, < 8.12.2","ecosystem":"npm"},{"name":"nodejs undici","fixed":["6.29.1"],"affected":">= 4.2.1, < 6.29.1","ecosystem":"vendor"},{"name":"nodejs undici","fixed":["7.30.1"],"affected":">= 7.0.0, < 7.30.1","ecosystem":"vendor"},{"name":"nodejs undici","fixed":["8.12.2"],"affected":">= 8.0.0, < 8.12.2","ecosystem":"vendor"}],"ecosystems":["npm","vendor"],"tags":["cwe-248","cwe-617","fetch","node.js","npm","package","undici"],"not_affected_if":["patched-version","tls-1.3-only"],"how_to_check":"- Run `npm ls undici` in each project and check whether the resolved version falls in the affected ranges: `>= 4.2.1, < 6.29.1`, `>= 7.0.0, < 7.30.1`, or `>= 8.0.0, < 8.12.2`.\n- Check whether your Node process fetches from or connects to untrusted or third-party HTTPS endpoints over TLS 1.2.","fix":"- Upgrade undici to `6.29.1`, `7.30.1`, or `8.12.2` depending on the major line in use.\n- Workaround until upgraded: restrict outbound TLS to 1.3 with `connect: { minVersion: 'TLSv1.3', maxVersion: 'TLSv1.3' }` on the client or agent, only where the target endpoints support TLS 1.3.","status":"open","published_at":"2026-10-15T19:17:46+00:00","first_seen_at":"2026-10-27T19:04:55+00:00","triaged_at":"2026-10-27T19:05:52+00:00","updated_at":"2026-10-27T19:33:18+00:00","category":"package","confidence":0.8,"triage":{"at":"2026-10-27T19:05:52Z","model":"claude-haiku-5-5","output":{"fix":"- Upgrade undici to `6.29.1`, `7.30.1`, or `8.12.2` depending on the major line in use.\n- Workaround until upgraded: restrict outbound TLS to 1.3 with `connect: { minVersion: 'TLSv1.3', maxVersion: 'TLSv1.3' }` on the client or agent, only where the target endpoints support TLS 1.3.","reach":"internet","title":"undici: a TLS 1.2 server can crash Node client via renegotiation","impact":"medium","summary":"undici, the HTTP client behind Node's global fetch, crashes the whole Node.js process when a TLS 1.2 server renegotiates the connection and presents a certificate whose hostname does not match. An attacker who controls or can impersonate the HTTPS endpoint can take down all in-flight requests and background work with one renegotiation.","category":"package","nicknames":[],"who_cares":["node.js","undici","npm","fetch"],"confidence":0.8,"needs_auth":"no","worst_case":"Client Node process crashes, taking down all in-flight requests","analyst_note":"","how_to_check":"- Run `npm ls undici` in each project and check whether the resolved version falls in the affected ranges: `>= 4.2.1, < 6.29.1`, `>= 7.0.0, < 7.30.1`, or `>= 8.0.0, < 8.12.2`.\n- Check whether your Node process fetches from or connects to untrusted or third-party HTTPS endpoints over TLS 1.2.","needs_analyst":false,"not_affected_if":["patched-version","tls-1.3-only"],"who_is_affected":"Any Node.js application that uses undici directly or the global fetch() on a version in an affected range is exposed when it connects to an HTTPS endpoint that negotiates TLS 1.2. The attacker must control or be able to reach the endpoint and present a CA-trusted certificate for a different hostname; no CA compromise is needed. Services that only talk to TLS 1.3 endpoints, or that have already moved to a patched undici, can skip the urgent action.","user_interaction":"no","needs_special_setup":"no","severity_if_unknown":"high"},"cost_usd":0.000763,"input_tokens":3855,"output_tokens":754,"severity_before":"high"},"analyst_status":null,"analyst_note":null,"search":"'-2026':15A,23A '-248':35B '-617':37B '-87018':16A,24A '1.2':9A,60B,107C,227C '1.3':232C,283C,309C '6.29.1':273C '7.30.1':274C '8.12.2':276C 'affect':187C,229C 'agent':297C 'altnam':149C 'assert':157C 'assertionerror':174C 'attack':75B,245C 'background':93B,220C 'becam':171C 'behind':47B 'ca':120C,242C 'ca-trust':119C 'cannot':301C 'cert':148C 'certif':11A,68B,122C,255C 'certificate-chang':10A 'chang':12A 'client':46B,102C,204C,295C 'code':161C 'compromis':191C,243C 'connect':64B,112C,280C,288C 'control':77B,169C,246C 'could':162C 'crash':52B,100C,202C 'cve':14A,22A 'cwe':34B,36B 'denial':4A 'destroy':142C 'differ':118C 'endpoint':83B,193C,248C,306C 'err':146C 'error':155C,160C,170C 'establish':114C,153C 'exampl':285C 'exploit':237C 'fetch':38B,51B,200C 'first':257C 'flight':90B,217C 'fqhp':20A 'ghsa':18A 'ghsa-qrxm-fqhp-jwvm':17A 'global':50B,199C 'handler':156C 'handshak':140C 'host':130C 'hostnam':70B,124C,135C 'http':45B 'http/1.1':182C 'http/2':184C 'https':82B,192C 'impact':98C 'imperson':80B 'in-flight':88B,215C 'initi':210C 'intent':265C 'invalid':150C 'jwvm':21A 'malici':189C 'match':73B,127C,258C,267C 'maxvers':291C 'minvers':289C 'never':163C 'node':48B 'node.js':39B,55B,131C,178C 'nodejs':28A,30A,32A 'npm':40B 'occur':164C,302C 'one':96B 'ordinari':253C 'outbound':279C 'packag':41B 'patch':269C 'path':185C 'peer':168C 'peer-control':167C 'present':66B,116C,251C 'process':56B,103C,179C,224C 'qrxm':19A 're':133C 're-run':132C 'reach':194C 'renegoti':13A,62B,97B,109C,139C,211C,236C,300C 'request':91B,129C,218C,260C 'requir':240C 'restrict':278C 'run':134C 'second':264C 'server':61B,108C,209C 'server-initi':208C 'servic':6A 'set':287C 'singl':207C 'socket':144C,154C 'support':235C,307C 'take':85B,212C 'target':305C 'termin':176C 'tls':8A,59B,106C,147C,226C,231C,282C,308C 'tlsv1.3':290C,292C 'trust':121C 'two':252C 'uncaught':173C 'undici':1A,25A,26A,27A,29A,31A,33A,42B,43B,99C,151C,196C,272C 'upgrad':270C 'url':261C 'valid':254C 'verif':136C 'via':7A 'vulner':2A 'whole':54B 'whose':69B,123C 'work':94B,221C 'workaround':277C","nicknames":[],"mitigations":[],"who_affected":"Any Node.js application that uses undici directly or the global fetch() on a version in an affected range is exposed when it connects to an HTTPS endpoint that negotiates TLS 1.2. The attacker must control or be able to reach the endpoint and present a CA-trusted certificate for a different hostname; no CA compromise is needed. Services that only talk to TLS 1.3 endpoints, or that have already moved to a patched undici, can skip the urgent action.","tier":"B","verified":{},"analyst_revisit_at":null,"first_public_at":"2026-10-15T19:17:46+00:00","kev":null,"cvss_vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","cvss_by":"GitHub","poc_count":0,"sources":[{"source":"ghsa","external_id":"GHSA-qrxm-fqhp-jwvm","url":"https://github.com/advisories/GHSA-qrxm-fqhp-jwvm","severity":"high","published_at":"2026-10-27T19:02:21+00:00","modified_at":"2026-10-27T19:02:22+00:00","first_seen_at":"2026-10-27T19:04:55+00:00","fetched_at":"2026-10-27T19:04:55+00:00","note":null},{"source":"nvd","external_id":"CVE-2026-87018","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-87018","severity":null,"published_at":"2026-10-15T19:17:46+00:00","modified_at":"2026-10-19T20:41:16+00:00","first_seen_at":"2026-10-27T19:33:18+00:00","fetched_at":"2026-10-27T19:33:18+00:00","note":null}],"documents":[],"notice":"Free to read at a human pace. An API with keys and an MCP server are in preparation; early access: hello@infrastack.ai"}