Every CVE Search/ Get API key

CVE-2026-119187

Forge: Denial of service in TLS record processing via call stack exhaustion

7.5 HighFix available

Forge (also called node-forge) is a native implementation of Transport Layer Security in JavaScript. Prior to 1.4.1, the affected implementation used forge.tls.createConnection(), TLS record processing, process() to process the relevant input or security decision. node-forge processed received TLS records recursively, consuming one JavaScript stack frame per record in a single input chunk. A remote peer could send thousands of small records together and exhaust the call stack, causing an uncaught exception and denial of service. This issue is fixed in version 1.4.1.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
None
User interaction
None

What an attacker can affect

Confidentiality
None
Integrity
None
Availability
High

Exploit likelihood

0.41%Unchanged since Oct 30, 2026
90%50%10%1%

What each source reports

CVE List Score used 7.5

Forge: Denial of service in TLS record processing via call stack exhaustion

Forge (also called node-forge) is a native implementation of Transport Layer Security in JavaScript. Prior to 1.4.1, the affected implementation used forge.tls.createConnection(), TLS record processing, process() to process the relevant input or security decision. node-forge processed received TLS records recursively, consuming one JavaScript stack frame per record in a single input chunk. A remote peer could send thousands of small records together and exhaust the call stack, causing an uncaught exception and denial of service. This issue is fixed in version 1.4.1.

Record
CVE-2026-119187
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-674
Updated
2026-11-04
EUVDEUVD-2026-113364 7.5

Forge (also called node-forge) is a native implementation of Transport Layer Security in JavaScript. Prior to 1.4.1, the affected implementation used forge.tls.createConnection(), TLS record processing, process() to process the relevant input or security decision. node-forge processed received TLS records recursively, consuming one JavaScript stack frame per record in a single input chunk. A remote peer could send thousands of small records together and exhaust the call stack, causing an uncaught exception and denial of service. This issue is fixed in version 1.4.1.

Record
EUVD-2026-113364
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Updated
2026-11-04
GitHub AdvisoriesGHSA-hqq3-7jhf-c5jx 7.5

Forge: Denial of service in TLS record processing via call stack exhaustion

Summary

Connections created with forge.tls.createConnection() processed received TLS records recursively, one stack level per record. A peer can send one chunk of thousands of small records, such as heartbeat records, which are accepted before the handshake, and process() throws RangeError: Maximum call stack size exceeded, which terminates Node.js processes that use the documented socket wiring. Fixed in node-forge 1.4.1.

Details

In lib/tls.js, c.process() reads one record and passes it to _update(), which calls the handler for the record type from ctTable. Every handler (tls.handleHeartbeat, tls.handleApplicationData, tls.handleHandshake for fragmented messages, tls.handleHelloRequest and the other handshake handlers) ends by calling c.process() again to continue with the next buffered record, or the next message in the same record. Each record therefore adds process → _update → handler to the call stack. In Node.js 24, about 2,300 eight-byte records (under 20 KB) in one chunk are enough for process() to throw RangeError: Maximum call stack size exceeded.

ctTable maps heartbeat records to tls.handleHeartbeat in every client and server state, so heartbeat records are processed before the handshake without any extension negotiation. The attack needs no authentication and no valid handshake messages. Both server connections (attacked by a client) and client connections (attacked by the server they connect to) are affected. Other record types recurse the same way: a handshake message fragmented over many records, many HelloRequest messages in one record, or many application data records after the handshake.

node-forge reports TLS protocol errors through the error callback, so applications do not normally wrap process() in try/catch. When process() is called from a Node.js socket data handler, as in the documented usage, the exception is uncaught and terminates the process. If the exception is caught, the connection is left partially processed and should be discarded.

No specification is violated; this is an implementation flaw (uncontrolled recursion).

The fix makes c.process() iterative. The record-reading code moves into _processRecord(), and c.process() runs it in a loop. A handler's call to c.process() without new data, made while records are being processed, now only flags that the loop should continue. Calls with new data are processed right away as before, so callback order and return values are unchanged.

Patches

Fixed in node-forge 1.4.1. Records are now processed in a loop, so the stack depth no longer depends on the number of records.

Workarounds

Wrap every call to connection.process() in try/catch, and on an exception close the connection (connection.close()) and destroy the underlying socket. This prevents the process crash but not the loss of the attacked connection.

Credits

Reported jointly by Ziyue Wang, Chenchen, Strick Sheng, Liyi Zhou, and Maurice Ng.

Proof of concept

Input: one chunk of N identical heartbeat records, each 8 bytes:

18 03 01 00 03 01 00 00 (content type 24 = heartbeat, TLS 1.0, length 3, heartbeat_request with a 0-byte payload)

// c = forge.tls.createConnection({server: true, ...}) var rec = forge.util.hexToBytes('1803010003010000'); c.process(new Array(5001).join(rec)); // 5,000 records, 40,000 bytes

On 1.4.0 (Node.js 24), process() throws RangeError: Maximum call stack size exceeded after about 2,300 records, before any handshake. The same happens for a client connection. In a Node.js server that calls c.process(data.toString('binary')) from socket.on('data', ...), a client sending these 40,000 bytes terminates the server process. On 1.4.1 all records are processed and the server keeps running.

Regression tests in tests/unit/tls.js, "record processing": 50,000 heartbeat records in one call in server and client mode, a handshake message fragmented over 50,000 records,…

Record
GHSA-hqq3-7jhf-c5jx
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-674
Updated
2026-11-02
GitHub AdvisoriesGHSA-gf8q-jrpm-jvxq No score

URL parsing in node-forge could lead to undesired behavior.

Impact

The regex used for the forge.util.parseUrl API would not properly parse certain inputs resulting in a parsed data structure that could lead to undesired behavior.

Patches

forge.util.parseUrl and other very old related URL APIs were removed in 1.0.0 in favor of letting applications use the more modern WHATWG URL Standard API.

Workarounds

Ensure code does not directly or indirectly call forge.util.parseUrl with untrusted input.

References

For more information

If you have any questions or comments about this advisory:

Record
GHSA-gf8q-jrpm-jvxq
Weakness
CWE-601
Updated
2026-11-02
NVD 7.5

Forge (also called node-forge) is a native implementation of Transport Layer Security in JavaScript. Prior to 1.4.1, the affected implementation used forge.tls.createConnection(), TLS record processing, process() to process the relevant input or security decision. node-forge processed received TLS records recursively, consuming one JavaScript stack frame per record in a single input chunk. A remote peer could send thousands of small records together and exhaust the call stack, causing an uncaught exception and denial of service. This issue is fixed in version 1.4.1.

Record
CVE-2026-119187
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-674
Updated
2026-11-04
OSV 7.5

Forge: Denial of service in TLS record processing via call stack exhaustion

Forge (also called node-forge) is a native implementation of Transport Layer Security in JavaScript. Prior to 1.4.1, the affected implementation used forge.tls.createConnection(), TLS record processing, process() to process the relevant input or security decision. node-forge processed received TLS records recursively, consuming one JavaScript stack frame per record in a single input chunk. A remote peer could send thousands of small records together and exhaust the call stack, causing an uncaught exception and denial of service. This issue is fixed in version 1.4.1.

Record
CVE-2026-119187
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-674
Updated
2026-11-07
Show 10 moreShow less
OSVGHSA-hqq3-7jhf-c5jx 7.5

Forge: Denial of service in TLS record processing via call stack exhaustion

Summary

Connections created with forge.tls.createConnection() processed received TLS records recursively, one stack level per record. A peer can send one chunk of thousands of small records, such as heartbeat records, which are accepted before the handshake, and process() throws RangeError: Maximum call stack size exceeded, which terminates Node.js processes that use the documented socket wiring. Fixed in node-forge 1.4.1.

Details

In lib/tls.js, c.process() reads one record and passes it to _update(), which calls the handler for the record type from ctTable. Every handler (tls.handleHeartbeat, tls.handleApplicationData, tls.handleHandshake for fragmented messages, tls.handleHelloRequest and the other handshake handlers) ends by calling c.process() again to continue with the next buffered record, or the next message in the same record. Each record therefore adds process → _update → handler to the call stack. In Node.js 24, about 2,300 eight-byte records (under 20 KB) in one chunk are enough for process() to throw RangeError: Maximum call stack size exceeded.

ctTable maps heartbeat records to tls.handleHeartbeat in every client and server state, so heartbeat records are processed before the handshake without any extension negotiation. The attack needs no authentication and no valid handshake messages. Both server connections (attacked by a client) and client connections (attacked by the server they connect to) are affected. Other record types recurse the same way: a handshake message fragmented over many records, many HelloRequest messages in one record, or many application data records after the handshake.

node-forge reports TLS protocol errors through the error callback, so applications do not normally wrap process() in try/catch. When process() is called from a Node.js socket data handler, as in the documented usage, the exception is uncaught and terminates the process. If the exception is caught, the connection is left partially processed and should be discarded.

No specification is violated; this is an implementation flaw (uncontrolled recursion).

The fix makes c.process() iterative. The record-reading code moves into _processRecord(), and c.process() runs it in a loop. A handler's call to c.process() without new data, made while records are being processed, now only flags that the loop should continue. Calls with new data are processed right away as before, so callback order and return values are unchanged.

Patches

Fixed in node-forge 1.4.1. Records are now processed in a loop, so the stack depth no longer depends on the number of records.

Workarounds

Wrap every call to connection.process() in try/catch, and on an exception close the connection (connection.close()) and destroy the underlying socket. This prevents the process crash but not the loss of the attacked connection.

Credits

Reported jointly by Ziyue Wang, Chenchen, Strick Sheng, Liyi Zhou, and Maurice Ng.

Proof of concept

Input: one chunk of N identical heartbeat records, each 8 bytes:

18 03 01 00 03 01 00 00 (content type 24 = heartbeat, TLS 1.0, length 3, heartbeat_request with a 0-byte payload)

// c = forge.tls.createConnection({server: true, ...}) var rec = forge.util.hexToBytes('1803010003010000'); c.process(new Array(5001).join(rec)); // 5,000 records, 40,000 bytes

On 1.4.0 (Node.js 24), process() throws RangeError: Maximum call stack size exceeded after about 2,300 records, before any handshake. The same happens for a client connection. In a Node.js server that calls c.process(data.toString('binary')) from socket.on('data', ...), a client sending these 40,000 bytes terminates the server process. On 1.4.1 all records are processed and the server keeps running.

Regression tests in tests/unit/tls.js, "record processing": 50,000 heartbeat records in one call in server and client mode, a handshake message fragmented over 50,000 records,…

Record
GHSA-hqq3-7jhf-c5jx
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-674
Updated
2026-11-02
OSVROOT-APP-NPM-CVE-2026-119187 7.5

CVE-2026-119187 in node-forge - Patched by Root

Root has patched CVE-2026-119187 in the node-forge package for Root:npm. Multiple fixed versions available.

Record
ROOT-APP-NPM-CVE-2026-119187
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Updated
2026-11-06
OSVUBUNTU-CVE-2026-119187 7.5

Forge (also called node-forge) is a native implementation of Transport Layer Security in JavaScript. Prior to 1.4.1, the affected implementation used forge.tls.createConnection(), TLS record processing, process() to process the relevant input or security decision. node-forge processed received TLS records recursively, consuming one JavaScript stack frame per record in a single input chunk. A remote peer could send thousands of small records together and exhaust the call stack, causing an uncaught exception and denial of service. This issue is fixed in version 1.4.1.

Record
UBUNTU-CVE-2026-119187
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Updated
2026-11-05
OSVAZL-112472 No score

CVE-2026-119187 affecting package python-tensorboard 2.16.2-6

Forge (also called node-forge) is a native implementation of Transport Layer Security in JavaScript. Prior to 1.4.1, the affected implementation used forge.tls.createConnection(), TLS record processing, process() to process the relevant input or security decision. node-forge processed received TLS records recursively, consuming one JavaScript stack frame per record in a single input chunk. A remote peer could send thousands of small records together and exhaust the call stack, causing an uncaught exception and denial of service. This issue is fixed in version 1.4.1.

Record
AZL-112472
Updated
2026-11-05
OSVCLSA-2026-1793790288 No score

TuxCare security update for node-forge (10 CVEs)

TuxCare rebuilt node-forge to address 10 CVEs. Fixed in 1.3.3-tuxcare.3.

Record
CLSA-2026-1793790288
Updated
2026-11-04
OSVCLSA-2026-1793801784 No score

TuxCare security update for node-forge (6 CVEs)

TuxCare rebuilt node-forge to address 6 CVEs. Fixed in 1.3.1-tuxcare.2.

Record
CLSA-2026-1793801784
Updated
2026-11-04
OSVCLSA-2026-1793808759 No score

TuxCare security update for node-forge (6 CVEs)

TuxCare rebuilt node-forge to address 6 CVEs. Fixed in 0.10.0-tuxcare.8.

Record
CLSA-2026-1793808759
Updated
2026-11-04
OSVCLSA-2026-1793814373 No score

TuxCare security update for node-forge (8 CVEs)

TuxCare rebuilt node-forge to address 8 CVEs. Fixed in 0.9.0-tuxcare.1.

Record
CLSA-2026-1793814373
Updated
2026-11-05
OSVGHSA-gf8q-jrpm-jvxq No score

URL parsing in node-forge could lead to undesired behavior.

Impact

The regex used for the forge.util.parseUrl API would not properly parse certain inputs resulting in a parsed data structure that could lead to undesired behavior.

Patches

forge.util.parseUrl and other very old related URL APIs were removed in 1.0.0 in favor of letting applications use the more modern WHATWG URL Standard API.

Workarounds

Ensure code does not directly or indirectly call forge.util.parseUrl with untrusted input.

References

For more information

If you have any questions or comments about this advisory:

Record
GHSA-gf8q-jrpm-jvxq
Weakness
CWE-601
Updated
2026-11-02
OSVROOT-APP-NPM-GHSA-gf8q-jrpm-jvxq No score

GHSA-gf8q-jrpm-jvxq in node-forge - Patched by Root

Root has patched GHSA-gf8q-jrpm-jvxq in the node-forge package for Root:npm. Multiple fixed versions available.

Record
ROOT-APP-NPM-GHSA-gf8q-jrpm-jvxq
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
node-forge
npm
before 1.0.0
1.0.0
node-forge
npm
through 1.4.0
1.4.1
python-tensorboard
Azure Linux:3
through 2.16.2-6 None known
node-forge
TuxCare:npm
From an advisory covering 10 CVEs
1.3.3-tuxcare.0 up to 1.3.3-tuxcare.3, plus listed versions
1.3.31.3.3-tuxcare.11.3.3-tuxcare.2
1.3.3-tuxcare.3
node-forge
TuxCare:npm
From an advisory covering 6 CVEs
1.3.1-tuxcare.0 up to 1.3.1-tuxcare.2, plus listed versions
1.3.11.3.1-tuxcare.1
1.3.1-tuxcare.2
node-forge
TuxCare:npm
From an advisory covering 6 CVEs
0.10.0-tuxcare.0 up to 0.10.0-tuxcare.8, plus listed versions
0.10.00.10.0-tuxcare.10.10.0-tuxcare.20.10.0-tuxcare.30.10.0-tuxcare.40.10.0-tuxcare.50.10.0-tuxcare.60.10.0-tuxcare.7
0.10.0-tuxcare.8
node-forge
TuxCare:npm
From an advisory covering 7 CVEs
0.9.0-tuxcare.0 up to 0.9.0-tuxcare.1, plus listed versions
0.9.0
0.9.0-tuxcare.1
node-forge
npm
before 1.4.1
1.4.1
node-forge
Root:npm
before 1.4.0-aikido.5
1.4.0-aikido.51.3.3-aikido.6
@rootio/node-forge
Root:npm
before 1.4.0-root.io.5
1.4.0-root.io.51.3.3-root.io.6
Show 4 moreShow less
Affected packages
PackageAffectedFixed
node-forge
Root:npm
before 1.0.0-aikido.1
1.0.0-aikido.1
@rootio/node-forge
Root:npm
before 1.0.0-root.io.1
1.0.0-root.io.1
node-node-forge
Ubuntu:20.04:LTS
All versions, plus listed versions
0.8.5~dfsg-20.9.1~dfsg-1
None known
node-node-forge
Ubuntu:22.04:LTS
All versions, plus listed versions
0.10.0~dfsg-31.2.1~dfsg-2
None known

History

History
RecordedChangedSources
affected
affectedOSV
affected, aliases, cwes, published, referencesOSV
affected, aliasesOSV
affected, aliasesEUVD, NVD, OSV
facts, referencesCVE List
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-119187 is a high vulnerability (CVSS 7.5) in Digitalbazaar Forge, published January 8, 2022. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.41%, the 36th percentile. Fixed in node-forge 1.0.0.

References

Show 7 moreShow less
This page doesn't list everything

Left out here: the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open