{"id":"CVE-2026-125333","kind":"vulnerability","aliases":["CVE-2026-125333","GHSA-6cv4-p8m7-4r25"],"related":[],"title":"Forge: ReDoS in forge.http response header and cookie trimming","description":"`forge.http` trims response header and `Set-Cookie` values with the regular expression `/\\s*$/`, which takes quadratic time on a long run of whitespace followed by another character. A server or on-path attacker can block a `forge.http` client for minutes with one large response header. Fixed in node-forge 1.4.3.\n\n### Details\n`_trimString()` in `lib/http.js` removes trailing whitespace with `str.replace(/\\s*$/, '')`. On a string of n whitespace characters followed by a non-whitespace character, the regular expression engine tries a match at each of the n positions and scans the rest of the run each time, so the work is O(n^2). `forge.http` calls `_trimString()` on every response header value read by `response.readHeader()`, and again on cookie names and values in `response.getCookies()`. There is no limit on header size.\n\nWith Node.js 24, an 80 KB header value takes about 4 seconds to parse, and 1 MB about 10 minutes, during which the event loop (or browser tab) is blocked.\n\n`forge.http` is not loaded by `require('node-forge')`. It is part of the `forge.all` bundle and needs a socket pool provided by the application (historically Flash sockets via `forge.xhr`), so few applications use it.\n\nThe fix trims trailing whitespace with a loop, as `lib/pem.js` has done since 1.4.1. The trimmed result is unchanged.\n\n#### Patches\nFixed in node-forge 1.4.3.\n\n#### Workarounds\nLimit the size of HTTP response headers before passing them to `forge.http`, for example in the socket pool's data handler.\n\n#### Resources\n- Related: GHSA-7wch-p9px-956x (ReDoS in PEM decoding, fixed in 1.4.1): https://github.com/digitalbazaar/forge/security/advisories/GHSA-7wch-p9px-956x\n\n#### Severity\nCVSS 3.1: CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H (5.9, Moderate)\nCVSS 4.0 (informational): CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N (8.2)\nCVSS 4.0 has no counterpart to 3.1's AC:H beyond AT:P and scores this higher; the severity rating follows CVSS 3.1.\n\n#### Credits\nReported by @manus-pi.\n\n### Proof of concept\n    var response = forge.http.createResponse();\n    var ws = new Array(40001).join('\\t ');\n    response.readHeader(forge.util.createBuffer(\n      'HTTP/1.1 200 OK\\r\\nX-A: a' + ws + 'X\\r\\n\\r\\n'));\n    // <= 1.4.2: about 4 seconds (quadratic in the whitespace length)\n    // 1.4.3: about 1 ms\n\nRegression tests are in tests/security/ghsa-6cv4-p8m7-4r25.js.\n\n### Impact\nApplications that use `forge.http` to talk to servers they don't control are affected. The server, or an on-path attacker, can send a response header that blocks the client's event loop for minutes, denying service to everything else in the process. There is no confidentiality or integrity impact.","summary":"node-forge's forge.http module trims HTTP response headers and cookies with a regular expression that takes quadratic time on long runs of whitespace. A malicious server or on-path attacker can block the client's event loop for minutes with one oversized header.","severity":"medium","cvss":5.9,"epss":null,"exploited":false,"exploited_at":null,"products":[{"name":"node-forge","fixed":["1.4.3"],"affected":">= 0.1.2, <= 1.4.2","ecosystem":"npm"}],"ecosystems":["npm"],"tags":["browser","cwe-1333","javascript","node","node-forge","package"],"not_affected_if":["no-forge-http-usage","server-controlled-by-you"],"how_to_check":"- Check the installed version with `npm ls node-forge`; affected range is `>= 0.1.2, <= 1.4.2`.\n- Search the code for `forge.http` or `require('node-forge').http` usage; the module is only in the `forge.all` bundle.\n- Confirm whether the application talks to servers it does not control through `forge.http`.","fix":"- node-forge: move to `1.4.3`","status":"open","published_at":"2026-11-10T19:21:10+00:00","first_seen_at":"2026-11-10T19:25:14+00:00","triaged_at":"2026-11-10T21:18:34+00:00","updated_at":"2026-11-10T21:18:34+00:00","category":"package","confidence":0.9,"triage":{"at":"2026-11-10T21:18:34Z","model":"claude-haiku-5-5","output":{"fix":"- node-forge: move to `1.4.3`","reach":"network","title":"node-forge: response header trimming lets a server stall the client","impact":"low","summary":"node-forge's forge.http module trims HTTP response headers and cookies with a regular expression that takes quadratic time on long runs of whitespace. A malicious server or on-path attacker can block the client's event loop for minutes with one oversized header.","audience":"developers","category":"package","nicknames":[],"who_cares":["node-forge","javascript","node","browser"],"confidence":0.9,"fix_status":"available","needs_auth":"no","worst_case":"Client process event loop blocked for minutes; denial of service only","analyst_note":"","how_to_check":"- Check the installed version with `npm ls node-forge`; affected range is `>= 0.1.2, <= 1.4.2`.\n- Search the code for `forge.http` or `require('node-forge').http` usage; the module is only in the `forge.all` bundle.\n- Confirm whether the application talks to servers it does not control through `forge.http`.","plain_action":"","product_name":"","needs_analyst":false,"not_affected_if":["no-forge-http-usage","server-controlled-by-you"],"who_is_affected":"Only applications that use the forge.http module to talk to servers they do not control are exposed, since a hostile server or on-path attacker can send the oversized header. The module is not loaded by a plain require of node-forge and needs a socket pool supplied by the application, so most projects can skip it. Limiting response header size before data reaches forge.http is a workaround the advisory names.","user_interaction":"no","product_ecosystem":"","needs_special_setup":"yes","severity_if_unknown":"unknown"},"cost_usd":0.000862,"input_tokens":5750,"output_tokens":573,"severity_before":"medium"},"analyst_status":null,"analyst_note":null,"search":"'-125333':12A,20A '-1333':26B '-2026':11A,19A '/av':347C,363C '/digitalbazaar/forge/security/advisories/ghsa-7wch-p9px-956x':341C '1':227C,445C '1.4.1':290C,338C '1.4.2':434C '1.4.3':131C,302C,443C '10':230C '2':184C '200':421C '24':214C '3.1':344C,346C,382C,398C '4':222C,436C '4.0':359C,362C,377C '40001':415C '4r25':17A '5.9':356C '6cv4':15A '7wch':329C '8.2':375C '80':216C '956x':331C 'ac':384C 'affect':466C 'anoth':105C 'applic':266C,274C,453C 'array':414C 'attack':65B,113C,474C 'beyond':386C 'block':67B,115C,241C,481C 'browser':24B,238C 'bundl':257C 'call':186C 'charact':106C,148C,155C 'client':69B,118C,483C 'concept':407C 'confidenti':500C 'control':464C 'cooki':8A,44B,86C,199C 'counterpart':380C 'credit':399C 'cve':10A,18A 'cvss':343C,345C,358C,361C,376C,397C 'cwe':25B 'data':323C 'decod':335C 'deni':489C 'detail':132C 'done':288C 'els':493C 'engin':159C 'event':71B,235C,485C 'everi':189C 'everyth':492C 'exampl':317C 'express':48B,91C,158C 'fix':126C,278C,297C,336C 'flash':268C 'follow':103C,149C,396C 'forg':1A,31B,35B,130C,250C,301C 'forge':23A 'forge.all':256C 'forge.http':4A,37B,79C,117C,185C,242C,315C,456C 'forge.http.createresponse':410C 'forge.util.createbuffer':419C 'forge.xhr':271C 'ghsa':14A,328C 'ghsa-6cv4-p8m7-4r25':13A 'ghsa-7wch-p9px-956x':327C 'github.com':340C 'github.com/digitalbazaar/forge/security/advisories/ghsa-7wch-p9px-956x':339C 'h':355C,385C 'h/pr':349C 'h/sc':371C 'handler':324C 'header':6A,42B,78B,82C,125C,191C,210C,218C,310C,479C 'higher':392C 'histor':267C 'http':40B,308C 'http/1.1':420C 'impact':452C,503C 'inform':360C 'integr':502C 'javascript':27B 'join':416C 'kb':217C 'l/at':365C 'larg':123C 'length':442C 'lib/http.js':135C 'lib/pem.js':286C 'limit':208C,304C 'load':245C 'long':54B,99C 'loop':72B,236C,284C,486C 'malici':59B 'manus':403C 'manus-pi':402C 'match':162C 'mb':228C 'minut':74B,120C,231C,488C 'moder':357C 'modul':38B 'ms':446C 'n':146C,167C,183C,374C,431C,433C 'n/a':354C 'n/ac':348C,364C 'n/i':353C 'n/s':351C 'n/sa':373C 'n/si':372C 'n/ui':350C,367C 'n/va':370C 'n/vc':368C 'n/vi':369C 'name':200C 'need':259C 'new':413C 'node':22A,28B,30B,34B,129C,249C,300C 'node-forg':29B,33B,128C,248C,299C 'node-forge':21A 'node.js':213C 'non':153C 'non-whitespac':152C 'nx':425C 'nx-a':424C 'o':182C 'ok':422C 'on-path':62B,110C,471C 'one':76B,122C 'overs':77B 'p':388C 'p/pr':366C 'p8m7':16A 'p9px':330C 'packag':32B 'pars':225C 'part':253C 'pass':312C 'patch':296C 'path':64B,112C,473C 'pem':334C 'pi':404C 'pool':262C,321C 'posit':168C 'process':496C 'proof':405C 'provid':263C 'quadrat':51B,95C,438C 'r':423C,430C,432C 'rate':395C 'read':193C 'redo':2A,332C 'regress':447C 'regular':47B,90C,157C 'relat':326C 'remov':136C 'report':400C 'requir':247C 'resourc':325C 'respons':5A,41B,81C,124C,190C,309C,409C,478C 'response.getcookies':204C 'response.readheader':195C,418C 'rest':172C 'result':293C 'run':55B,100C,175C 'scan':170C 'score':390C 'second':223C,437C 'send':476C 'server':60B,108C,460C,468C 'servic':490C 'set':85C 'set-cooki':84C 'sever':342C,394C 'sinc':289C 'size':211C,306C 'socket':261C,269C,320C 'str.replace':140C 'string':144C 'tab':239C 'take':50B,94C,220C 'talk':458C 'test':448C 'tests/security/ghsa-6cv4-p8m7-4r25.js':451C 'time':52B,96C,177C 'trail':137C,280C 'tri':160C 'trim':9A,39B,80C,279C,292C 'trimstr':133C,187C 'u/c':352C 'unchang':295C 'use':275C,455C 'valu':87C,192C,202C,219C 'var':408C,411C 'via':270C 'whitespac':57B,102C,138C,147C,154C,281C,441C 'work':180C 'workaround':303C 'ws':412C,428C 'x':429C","nicknames":[],"mitigations":[],"who_affected":"Only applications that use the forge.http module to talk to servers they do not control are exposed, since a hostile server or on-path attacker can send the oversized header. The module is not loaded by a plain require of node-forge and needs a socket pool supplied by the application, so most projects can skip it. Limiting response header size before data reaches forge.http is a workaround the advisory names.","tier":"C","verified":{},"analyst_revisit_at":null,"fix_status":"available","audience":"developers","plain_action":null,"pkeys":["nodeforge"],"ptokens":["forge","node"],"labels":["browser","cwe1333","javascript","medium","node","nodeforge","npm","package"],"campaign_type":null,"search_a":"'-125333':12A,20A '-2026':11A,19A '4r25':17A '6cv4':15A 'cooki':8A 'cve':10A,18A 'forg':1A 'forge':23A 'forge.http':4A 'ghsa':14A 'ghsa-6cv4-p8m7-4r25':13A 'header':6A 'node':22A 'node-forge':21A 'p8m7':16A 'redo':2A 'respons':5A 'trim':9A","search_b":"'-1333':26B 'attack':65B 'block':67B 'browser':24B 'client':69B 'cooki':44B 'cwe':25B 'event':71B 'express':48B 'forg':31B,35B 'forge.http':37B 'header':42B,78B 'http':40B 'javascript':27B 'long':54B 'loop':72B 'malici':59B 'minut':74B 'modul':38B 'node':28B,30B,34B 'node-forg':29B,33B 'on-path':62B 'one':76B 'overs':77B 'packag':32B 'path':64B 'quadrat':51B 'regular':47B 'respons':41B 'run':55B 'server':60B 'take':50B 'time':52B 'trim':39B 'whitespac':57B","search_c":"'/av':347C,363C '/digitalbazaar/forge/security/advisories/ghsa-7wch-p9px-956x':341C '1':227C,445C '1.4.1':290C,338C '1.4.2':434C '1.4.3':131C,302C,443C '10':230C '2':184C '200':421C '24':214C '3.1':344C,346C,382C,398C '4':222C,436C '4.0':359C,362C,377C '40001':415C '5.9':356C '7wch':329C '8.2':375C '80':216C '956x':331C 'ac':384C 'affect':466C 'anoth':105C 'applic':266C,274C,453C 'array':414C 'attack':113C,474C 'beyond':386C 'block':115C,241C,481C 'browser':238C 'bundl':257C 'call':186C 'charact':106C,148C,155C 'client':118C,483C 'concept':407C 'confidenti':500C 'control':464C 'cooki':86C,199C 'counterpart':380C 'credit':399C 'cvss':343C,345C,358C,361C,376C,397C 'data':323C 'decod':335C 'deni':489C 'detail':132C 'done':288C 'els':493C 'engin':159C 'event':235C,485C 'everi':189C 'everyth':492C 'exampl':317C 'express':91C,158C 'fix':126C,278C,297C,336C 'flash':268C 'follow':103C,149C,396C 'forg':130C,250C,301C 'forge.all':256C 'forge.http':79C,117C,185C,242C,315C,456C 'forge.http.createresponse':410C 'forge.util.createbuffer':419C 'forge.xhr':271C 'ghsa':328C 'ghsa-7wch-p9px-956x':327C 'github.com':340C 'github.com/digitalbazaar/forge/security/advisories/ghsa-7wch-p9px-956x':339C 'h':355C,385C 'h/pr':349C 'h/sc':371C 'handler':324C 'header':82C,125C,191C,210C,218C,310C,479C 'higher':392C 'histor':267C 'http':308C 'http/1.1':420C 'impact':452C,503C 'inform':360C 'integr':502C 'join':416C 'kb':217C 'l/at':365C 'larg':123C 'length':442C 'lib/http.js':135C 'lib/pem.js':286C 'limit':208C,304C 'load':245C 'long':99C 'loop':236C,284C,486C 'manus':403C 'manus-pi':402C 'match':162C 'mb':228C 'minut':120C,231C,488C 'moder':357C 'ms':446C 'n':146C,167C,183C,374C,431C,433C 'n/a':354C 'n/ac':348C,364C 'n/i':353C 'n/s':351C 'n/sa':373C 'n/si':372C 'n/ui':350C,367C 'n/va':370C 'n/vc':368C 'n/vi':369C 'name':200C 'need':259C 'new':413C 'node':129C,249C,300C 'node-forg':128C,248C,299C 'node.js':213C 'non':153C 'non-whitespac':152C 'nx':425C 'nx-a':424C 'o':182C 'ok':422C 'on-path':110C,471C 'one':122C 'p':388C 'p/pr':366C 'p9px':330C 'pars':225C 'part':253C 'pass':312C 'patch':296C 'path':112C,473C 'pem':334C 'pi':404C 'pool':262C,321C 'posit':168C 'process':496C 'proof':405C 'provid':263C 'quadrat':95C,438C 'r':423C,430C,432C 'rate':395C 'read':193C 'redo':332C 'regress':447C 'regular':90C,157C 'relat':326C 'remov':136C 'report':400C 'requir':247C 'resourc':325C 'respons':81C,124C,190C,309C,409C,478C 'response.getcookies':204C 'response.readheader':195C,418C 'rest':172C 'result':293C 'run':100C,175C 'scan':170C 'score':390C 'second':223C,437C 'send':476C 'server':108C,460C,468C 'servic':490C 'set':85C 'set-cooki':84C 'sever':342C,394C 'sinc':289C 'size':211C,306C 'socket':261C,269C,320C 'str.replace':140C 'string':144C 'tab':239C 'take':94C,220C 'talk':458C 'test':448C 'tests/security/ghsa-6cv4-p8m7-4r25.js':451C 'time':96C,177C 'trail':137C,280C 'tri':160C 'trim':80C,279C,292C 'trimstr':133C,187C 'u/c':352C 'unchang':295C 'use':275C,455C 'valu':87C,192C,202C,219C 'var':408C,411C 'via':270C 'whitespac':102C,138C,147C,154C,281C,441C 'work':180C 'workaround':303C 'ws':412C,428C 'x':429C","cause_entry":null,"cause_path":null,"disclosures_checked_at":null,"first_public_at":"2026-11-04T01:09:45+00:00","kev":null,"cvss_vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H","cvss_by":"GitHub","poc_count":0,"sources":[{"source":"nvd","external_id":"CVE-2026-125333","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-125333","severity":null,"published_at":"2026-11-10T19:21:10+00:00","modified_at":"2026-11-10T19:21:10+00:00","first_seen_at":"2026-11-10T19:25:14+00:00","fetched_at":"2026-11-10T19:25:14+00:00","note":null},{"source":"ghsa","external_id":"GHSA-6cv4-p8m7-4r25","url":"https://github.com/advisories/GHSA-6cv4-p8m7-4r25","severity":"medium","published_at":"2026-11-10T21:16:22+00:00","modified_at":"2026-11-10T21:16:23+00:00","first_seen_at":"2026-11-10T21:17:48+00:00","fetched_at":"2026-11-10T21:17:48+00:00","note":null}],"documents":[{"id":117499,"url":"https://github.com/digitalbazaar/forge/commit/326a4d0903ee46358bc849a5c3fd96d9c21489bd","title":"Patch: github.com","kind":"other","source":"nvd","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Patch: github.com"},{"id":117497,"url":"https://github.com/digitalbazaar/forge/releases/tag/v1.4.3","title":"Release notes: github.com","kind":"release","source":"nvd","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Release notes: github.com"},{"id":117501,"url":"https://github.com/digitalbazaar/forge/security/advisories/GHSA-6cv4-p8m7-4r25","title":"Vendor advisory: github.com","kind":"vendor","source":"nvd","publisher":"vendor","text":null,"published_at":"2026-11-04T01:09:45+00:00","relation":"advisory","confidence":null,"note":"Vendor advisory: github.com"},{"id":118799,"url":"https://api.github.com/repos/digitalbazaar/forge/security-advisories/GHSA-6cv4-p8m7-4r25","title":"Maintainer's advisory: api.github.com","kind":"vendor","source":"ghsa","publisher":"vendor","text":null,"published_at":null,"relation":"advisory","confidence":null,"note":"Maintainer's advisory: api.github.com"},{"id":118796,"url":"https://github.com/digitalbazaar/forge/pull/1169","title":"Patch: github.com","kind":"other","source":"ghsa","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Patch: github.com"}],"disclosures":[],"exploit_sources":[],"notice":"Free to read, with fair use of about 60 pages a minute. For higher limits or API access: sales@infrastack.ai"}