GHSA-W4XR-HQV8-CH44

Vulnerability from github – Published: 2026-11-10 21:17 – Updated: 2026-11-10 21:17
VLAI
Summary
Forge: TLS client crash on an unsupported ServerHello compression method
Details

Summary

A forge.tls client accepts any compression method in the ServerHello, although it only offers no compression. An unknown method makes connection.process() throw an uncaught Error when the client handles ServerHelloDone, before the server is authenticated. A malicious server or an on-path attacker can use this to terminate a Node.js process. Fixed in node-forge 1.4.3.

Details

The client's ClientHello offers only the null compression method. tls.parseHelloMessage() in lib/tls.js stores the ServerHello's compression_method for the client without checking it (the code has a TODO: handle compression methods). When the client handles ServerHelloDone it calls tls.createConnectionState(), which throws Error('Unsupported compression algorithm.') for any method other than null (0) and deflate (1). The exception propagates out of connection.process().

The ServerHello isn't authenticated until the server's Finished message, so an on-path attacker can change the compression byte of a genuine ServerHello; the certificate chain still verifies. Applications that pass socket data to process() without catching exceptions terminate. This includes forge.tls.wrapSocket, which calls process() from its socket data handler, and forge.http, which uses it. A deflate (1) method, also never offered, makes the handshake fail later with an error instead of a crash.

Servers are not affected: a server always selects no compression.

The fix fails the handshake with an illegal_parameter alert, through the connection's error callback, when the ServerHello selects any compression method other than null.

Patches

Fixed in node-forge 1.4.3.

Workarounds

Catch exceptions thrown by connection.process() and close the socket.

Resources

  • RFC 5246, section 7.4.1.3 (Server Hello): https://www.rfc-editor.org/rfc/rfc5246#section-7.4.1.3
  • Related: GHSA-525v-9gp9-w22h (another TLS client crash during the handshake, fixed in 1.4.1): https://github.com/digitalbazaar/forge/security/advisories/GHSA-525v-9gp9-w22h

Severity

CVSS 3.1: CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H (5.9, Moderate) CVSS 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) CVSS 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.

Credits

Reported by @alienkeric.

Proof of concept

A server (or on-path attacker) sends a ServerHello with compression_method 0xff, followed by a valid Certificate and ServerHelloDone:

client.handshake();
client.process(serverHello + certificate + serverHelloDone);
// <= 1.4.2: throws Error: Unsupported compression algorithm.
// 1.4.3: error callback with "Unsupported compression method."

The reporter's PoC (a CA-issued server certificate and the default verify callback) is in tests/pocs/ghsa-w4xr-hqv8-ch44.js, and regression tests are in tests/unit/tls.js.

Impact

Applications that use forge.tls as a client (directly, through forge.tls.wrapSocket, or through forge.http) and pass data from a network socket to connection.process() are affected. The server they connect to, or an on-path attacker, can make process() throw before the server is authenticated; if the application doesn't catch it, the Node.js process terminates, dropping all its connections. Servers built on forge.tls are not affected. There is no confidentiality or integrity impact.

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 1.4.2"
      },
      "package": {
        "ecosystem": "npm",
        "name": "node-forge"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "1.4.3"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-125332"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-20",
      "CWE-248"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-11-10T21:17:14Z",
    "nvd_published_at": null,
    "severity": "MODERATE"
  },
  "details": "### Summary\nA `forge.tls` client accepts any compression method in the ServerHello, although it only offers no compression. An unknown method makes `connection.process()` throw an uncaught `Error` when the client handles ServerHelloDone, before the server is authenticated. A malicious server or an on-path attacker can use this to terminate a Node.js process. Fixed in node-forge 1.4.3.\n\n### Details\nThe client\u0027s ClientHello offers only the `null` compression method. `tls.parseHelloMessage()` in `lib/tls.js` stores the ServerHello\u0027s `compression_method` for the client without checking it (the code has a `TODO: handle compression methods`). When the client handles ServerHelloDone it calls `tls.createConnectionState()`, which throws `Error(\u0027Unsupported compression algorithm.\u0027)` for any method other than `null` (0) and `deflate` (1). The exception propagates out of `connection.process()`.\n\nThe ServerHello isn\u0027t authenticated until the server\u0027s Finished message, so an on-path attacker can change the compression byte of a genuine ServerHello; the certificate chain still verifies. Applications that pass socket data to `process()` without catching exceptions terminate. This includes `forge.tls.wrapSocket`, which calls `process()` from its socket data handler, and `forge.http`, which uses it. A `deflate` (1) method, also never offered, makes the handshake fail later with an error instead of a crash.\n\nServers are not affected: a server always selects no compression.\n\nThe fix fails the handshake with an `illegal_parameter` alert, through the connection\u0027s `error` callback, when the ServerHello selects any compression method other than `null`.\n\n#### Patches\nFixed in node-forge 1.4.3.\n\n#### Workarounds\nCatch exceptions thrown by `connection.process()` and close the socket.\n\n#### Resources\n- RFC 5246, section 7.4.1.3 (Server Hello): https://www.rfc-editor.org/rfc/rfc5246#section-7.4.1.3\n- Related: GHSA-525v-9gp9-w22h (another TLS client crash during the handshake, fixed in 1.4.1): https://github.com/digitalbazaar/forge/security/advisories/GHSA-525v-9gp9-w22h\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\u0027s AC:H beyond AT:P and scores this higher; the severity rating follows CVSS 3.1.\n\n#### Credits\nReported by @alienkeric.\n\n### Proof of concept\nA server (or on-path attacker) sends a ServerHello with `compression_method` 0xff, followed by a valid Certificate and ServerHelloDone:\n\n    client.handshake();\n    client.process(serverHello + certificate + serverHelloDone);\n    // \u003c= 1.4.2: throws Error: Unsupported compression algorithm.\n    // 1.4.3: error callback with \"Unsupported compression method.\"\n\nThe reporter\u0027s PoC (a CA-issued server certificate and the default verify callback) is in tests/pocs/ghsa-w4xr-hqv8-ch44.js, and regression tests are in tests/unit/tls.js.\n\n### Impact\nApplications that use `forge.tls` as a client (directly, through `forge.tls.wrapSocket`, or through `forge.http`) and pass data from a network socket to `connection.process()` are affected. The server they connect to, or an on-path attacker, can make `process()` throw before the server is authenticated; if the application doesn\u0027t catch it, the Node.js process terminates, dropping all its connections. Servers built on `forge.tls` are not affected. There is no confidentiality or integrity impact.",
  "id": "GHSA-w4xr-hqv8-ch44",
  "modified": "2026-11-10T21:17:14Z",
  "published": "2026-11-10T21:17:14Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/digitalbazaar/forge/security/advisories/GHSA-w4xr-hqv8-ch44"
    },
    {
      "type": "WEB",
      "url": "https://github.com/digitalbazaar/forge/pull/1169"
    },
    {
      "type": "WEB",
      "url": "https://github.com/digitalbazaar/forge/commit/1d9816d333c23c523ef2bd8b24282c87db2654ef"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/digitalbazaar/forge"
    },
    {
      "type": "WEB",
      "url": "https://github.com/digitalbazaar/forge/releases/tag/v1.4.3"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Forge: TLS client crash on an unsupported ServerHello compression method"
}



Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Drag nodes to arrange them. Double-click a related vulnerability to open it, or a source to visit its link. The Physics button on the left tunes the layout and the simulation; the legend at the bottom left hides or shows nodes by kind and by sighting type.

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.
Vulnerability timeline

Sightings and recorded dates, grouped by day · UTC

JSON
How durations are calculated

Following the VTEM framework (Black Hat USA 2015), time to patch starts when the vendor or a coordinator was informed, total time to patch at discovery, and disclosure to patch at public disclosure; vendor response time runs from the report to its acknowledgement. Time to exploit and time unpatched start at the earliest discovery or report, falling back to public disclosure. Unpatched time ends at the first recorded patch, or the calculation time when no patch is recorded. Exploitation to patch shows the interval between those two events; a published proof of concept is a public exploit, not exploitation.

Each result shows its source dates. A negative interval means the end event came first; when date-only inputs leave the order open, the result says so. Date-only inputs are approximate. The earliest evidence wins: KEV report dates and sightings are labelled as such. Records describing another vulnerability are listed but never calculated from, and a PoC alone does not establish exploitation. Missing patch evidence does not prove that no patch exists. Filters below change the event list only.

Events included in the timeline

Loading timeline…


    Loading…

    Loading…

    Loading…

    Related by attack behaviour

    Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.