Skip to main content
Vulnerability Database/CVE-2026-68904

CVE-2026-68904: node-opcua DOS Vulnerability

CVE-2026-68904 is a denial of service vulnerability in node-opcua that causes resource exhaustion through repeated reconnection cycles. This post explains its impact, affected versions, and mitigation steps.

Updated:

CVE-2026-68904 Overview

CVE-2026-68904 is a resource exhaustion vulnerability [CWE-400] in node-opcua, an OPC UA implementation for TypeScript and Node.js. Versions from 2.0.0 through 2.169.x are affected. When an OPC UA server experiences clock skew and returns BadInvalidTimestamp responses, node-opcua clients using the default keepSessionAlive setting misinterpret the server-originated ServiceFault as a network outage. The client then forces repeated transport reconnects, leaking sockets in FIN-WAIT-2 and accumulating file descriptors and memory. Sustained repetition at the keepalive interval exhausts client resources until the process or container terminates. The issue is fixed in version 2.170.0.

Critical Impact

Remote OPC UA servers with clock skew can trigger unbounded reconnect loops in node-opcua clients, causing file descriptor and memory exhaustion until the client process crashes.

Affected Products

  • node-opcua versions 2.0.0 through 2.169.x
  • Node.js and TypeScript applications using node-opcua client libraries
  • Industrial control system (ICS) integrations relying on node-opcua for OPC UA communication

Discovery Timeline

  • 2026-09-16 - CVE-2026-68904 published to the National Vulnerability Database
  • 2026-09-16 - Last updated in NVD database

Technical Details for CVE-2026-68904

Vulnerability Analysis

The vulnerability resides in two interacting components of the node-opcua client. The ClientSessionKeepAliveManager._ping_server routine issues periodic keepalive requests to detect session health. When the server returns a ServiceFault such as BadInvalidTimestamp caused by clock skew, the manager classifies the application-layer fault as a transport failure. This misclassification triggers an immediate transport reconnect through ClientTCP_transport. The reconnect cycle repeats every keepAliveInterval, producing a persistent loop that consumes client resources without any authentication requirement.

Root Cause

Two distinct defects combine to produce the exhaustion condition. First, _ping_server does not distinguish server-originated OPC UA ServiceFault responses from actual socket or protocol errors. Second, ClientTCP_transport._on_ACK_response calls socket.end() after a failed HEL/ACK negotiation instead of destroying the socket. When the peer does not send FIN, the local half-closed socket lingers in FIN-WAIT-2, holding a file descriptor and buffers. Repeated reconnect attempts accumulate these orphaned sockets, exhausting system resources.

Attack Vector

An attacker capable of influencing an OPC UA server's clock, or an operator of a malicious or misconfigured server, can trigger the loop simply by responding with BadInvalidTimestamp to keepalive requests. No credentials or user interaction are required. The vulnerability is exploitable over the network against any node-opcua client that connects to the affected server with default keepalive settings.

typescript
// Patch: release socket immediately on HEL/ACK failure
// Source: https://github.com/node-opcua/node-opcua/commit/1959cbb8946b386d2e24a1cce05b7148099d36e7
this._counter += 1;

if (err || !data) {
-    externalCallback(err || new Error("no data"));
     if (this._socket) {
-        this._socket.end();
+        const s = this._socket;
+        this._socket = null;
+        s.destroy();
     }
+    externalCallback(err || new Error("no data"));
} else {
     this._handle_ACK_response(data, externalCallback);
}
typescript
// Patch: distinguish server-originated faults from transport errors
// Source: https://github.com/node-opcua/node-opcua/commit/4d59197e2dbd82791d7f36dad7da178715e0c27a
import type { StatusCode } from "node-opcua-status-code";
import { StatusCodes } from "node-opcua-status-code";

interface ServiceFaultAnnotatedError extends Error {
    response?: {
        responseHeader?: {
            serviceResult?: StatusCode;
        };
    };
}

Detection Methods for CVE-2026-68904

Indicators of Compromise

  • Repeated node-opcua client log entries showing keepalive failures paired with reconnect attempts at the configured keepAliveInterval.
  • Growing count of TCP sockets in FIN-WAIT-2 state associated with the client process.
  • Steadily increasing file descriptor and memory usage in Node.js processes running node-opcua clients.
  • Server-side BadInvalidTimestamp responses correlated with client reconnect spikes.

Detection Strategies

  • Inspect package.json and lockfiles across Node.js deployments for node-opcua versions earlier than 2.170.0.
  • Monitor process-level file descriptor counts using lsof -p <pid> or /proc/<pid>/fd for node-opcua client processes.
  • Enable node-opcua debug logging and watch for repeated keepalive_failure events emitted by ClientSessionKeepAliveManager.

Monitoring Recommendations

  • Alert on Node.js process memory or file descriptor growth exceeding baseline in industrial workloads.
  • Track TCP socket states with ss -tan state fin-wait-2 and alert when counts exceed a threshold per host.
  • Correlate OPC UA server clock synchronization health with client reconnect metrics.

How to Mitigate CVE-2026-68904

Immediate Actions Required

  • Upgrade all node-opcua client deployments to version 2.170.0 or later.
  • Audit dependency trees for transitive uses of node-opcua and rebuild affected artifacts.
  • Verify NTP synchronization on all OPC UA servers to reduce clock skew that triggers BadInvalidTimestamp responses.
  • Restart long-running node-opcua client processes after patching to release leaked sockets.

Patch Information

The fix is delivered in node-opcua v2.170.0. It introduces exponential backoff for consecutive keepalive ServiceFaults, distinguishes server-originated faults from transport errors, and calls socket.destroy() on HEL/ACK failure. Details are documented in the GHSA-r2pf-9cw4-5j65 advisory and consolidated in Pull Request #1497.

Workarounds

  • Disable the default keepSessionAlive behavior on client sessions where feasible until the upgrade is applied.
  • Increase the keepAliveInterval to slow socket accumulation and buy time to detect the condition.
  • Restrict client connections to trusted OPC UA servers with verified time synchronization.
  • Apply process-level ulimit and container memory limits so that exhaustion triggers a controlled restart rather than host-wide impact.
bash
# Upgrade node-opcua to the patched release
npm install node-opcua@^2.170.0

# Verify installed version
npm ls node-opcua

# Inspect FIN-WAIT-2 socket accumulation on Linux hosts
ss -tan state fin-wait-2 | wc -l

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.