Register for the AI for Security Summit: Join Figma, Perplexity & Wiz

CVE-2026-68904
JavaScript vulnerability analysis and mitigation

Overview

CVE-2026-68904 is a TCP socket leak vulnerability in node-opcua, an OPC UA implementation for TypeScript and Node.js, that causes uncontrolled resource consumption (CWE-400) leading to process or container crash via OOM kill. The flaw affects all versions from 2.0.0 up to (but not including) 2.170.0, including the node-opcua, node-opcua-client, and node-opcua-transport npm packages. It was discovered by Marco Velluso and published as a GitHub Security Advisory on September 16, 2026, with the fix merged on April 27, 2026. The vulnerability carries a CVSS v3.1 base score of 7.0 (High) (GitHub Advisory).

Technical details

The vulnerability stems from two compounding bugs in the node-opcua client library. Bug #1 (ClientTCP_transport._on_ACK_response in node-opcua-transport/src/client_tcp_transport.ts): when a HEL/ACK handshake fails during reconnection, the error handler calls socket.end() instead of socket.destroy(). socket.end() sends a TCP FIN and waits for the peer to close its side; if the peer (e.g., an industrial PLC) does not respond, the socket remains in FIN-WAIT-2 state indefinitely, leaking a file descriptor. Bug #2 (ClientSessionKeepAliveManager._ping_server in node-opcua-client/src/client_session_keepalive_manager.ts): when the OPC UA server's clock is skewed relative to the client, the server returns a BadInvalidTimestamp ServiceFault; the keepalive manager incorrectly treats this application-level fault as a fatal network outage and triggers a full transport-level reconnection on every keepalive cycle. Combined, each keepalive interval (default 3000 ms) spawns a new reconnection attempt that leaks one FIN-WAIT-2 socket, accumulating approximately 20 leaked sockets per minute and ~1,200 per hour until resources are exhausted (GitHub Advisory, Fix PR #1497).

Impact

Successful triggering of this vulnerability causes unbounded accumulation of TCP sockets in FIN-WAIT-2 state, exhausting file descriptors and memory in the affected Node.js process or container. The primary impact is a Denial of Service (DoS) — the client process is eventually killed by the operating system's OOM killer, disrupting any OPC UA-based industrial or IoT integration relying on the affected client. Secondary confidentiality and integrity impacts are rated Low, as the vulnerability does not directly expose data or allow data modification, but a crashed client may lose buffered telemetry or control state (GitHub Advisory).

Exploitability

No public proof-of-concept exploit code or in-the-wild exploitation has been reported. The vulnerability is triggered by the default configuration (keepSessionAlive: true) when connecting to an OPC UA server with a clock skew exceeding the server's timestamp tolerance — a condition that can occur naturally with industrial PLCs or can be deliberately induced by a network-adjacent attacker who can manipulate server time. The EPSS score is 0.0, and the vulnerability is not listed in the CISA Known Exploited Vulnerabilities (KEV) catalog. NVD's SSVC assessment classifies exploitation as "none" and the attack as not automatable (GitHub Advisory).

Exploitation steps

  1. Identify a target: Locate a Node.js application using node-opcua versions 2.0.0–2.169.x with keepSessionAlive: true (the default) connecting to an OPC UA server endpoint.
  2. Induce clock skew: Arrange for the OPC UA server's system clock to be skewed more than the server's timestamp tolerance window ahead of the client (e.g., ~50 minutes). This can occur naturally with misconfigured PLCs or be induced by an attacker with access to the server's time configuration.
  3. Trigger BadInvalidTimestamp responses: With the clock skew in place, the client's RequestHeader.timestamp will fall outside the server's tolerance, causing the server to return BadInvalidTimestamp ServiceFault responses to keepalive read requests.
  4. Observe reconnection loop: The ClientSessionKeepAliveManager._ping_server() method misclassifies the BadInvalidTimestamp fault as a network outage and calls terminateConnection(), triggering a full transport reconnect every keepAliveInterval milliseconds (default: 3000 ms).
  5. Accumulate leaked sockets: Each reconnection attempt fails HEL/ACK negotiation and calls socket.end() (pre-fix), leaving the socket in FIN-WAIT-2. Monitor with ss -antp | grep FIN-WAIT-2 | wc -l to observe the growing count.
  6. Resource exhaustion: After hours of accumulation (~1,200 sockets/hour at default interval), the process exhausts file descriptors or memory and is killed by the OOM killer, achieving a Denial of Service (GitHub Advisory).

Indicators of compromise

  • Network: Growing number of TCP connections in FIN-WAIT-2 state from the node-opcua client host to the OPC UA server port (detectable via ss -antp | grep FIN-WAIT-2 | wc -l or netstat -an | grep FIN_WAIT2).
  • Logs: Repeated warning log entries from client_session_keepalive_manager.ts such as "warning : ClientSessionKeepAliveManager#ping_server" followed by "Keep alive has failed, considering a network outage is in place, forcing a reconnection" at every keepalive interval.
  • Process: Rapid cycling of OPC UA reconnection events in application logs; eventual OOM kill of the Node.js process visible in system logs (e.g., dmesg | grep -i oom or container runtime logs showing OOMKilled status).
  • File System / OS: File descriptor exhaustion errors (EMFILE: too many open files) in Node.js process logs preceding the crash (GitHub Advisory).

Mitigation and workarounds

Upgrade to node-opcua, node-opcua-client, and node-opcua-transport version 2.170.0 or later, which fixes both root causes: socket.destroy() is now used instead of socket.end() in _on_ACK_response, and _ping_server now distinguishes recoverable ServiceFaults (like BadInvalidTimestamp) from true transport failures, applying exponential backoff (2x, 4x, 8x... capped at 60s) instead of triggering reconnection. As a temporary workaround prior to upgrading, ensure NTP synchronization between OPC UA clients and servers to eliminate clock skew exceeding the server's timestamp tolerance, which prevents the BadInvalidTimestamp fault from being generated. Additionally, monitoring for FIN-WAIT-2 socket accumulation can provide early warning of the condition (GitHub Advisory, Fix PR #1497).

Additional resources


SourceThis report was generated using AI

Related JavaScript vulnerabilities:

CVE ID

Severity

Score

Technologies

Component name

CISA KEV exploit

Has fix

Published date

CVE-2026-61560CRITICAL9.8
  • JavaScript logoJavaScript
  • @zereight/mcp-gitlab
NoYesSep 15, 2026
CVE-2026-61568CRITICAL9.6
  • JavaScript logoJavaScript
  • @zereight/mcp-gitlab
NoYesSep 15, 2026
CVE-2026-61559CRITICAL9.6
  • JavaScript logoJavaScript
  • @zereight/mcp-gitlab
NoYesSep 15, 2026
CVE-2026-63671HIGH8.1
  • JavaScript logoJavaScript
  • @nuxtjs/mdc
NoYesSep 16, 2026
CVE-2026-68904HIGH7
  • JavaScript logoJavaScript
  • node-opcua
NoYesSep 16, 2026

Free Vulnerability Assessment

Benchmark your Cloud Security Posture

Evaluate your cloud security practices across 9 security domains to benchmark your risk level and identify gaps in your defenses.

Request assessment

Get a personalized demo

Ready to see Wiz in action?

"Best User Experience I have ever seen, provides full visibility to cloud workloads."
David EstlickCISO
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
Adam FletcherChief Security Officer
"We know that if Wiz identifies something as critical, it actually is."
Greg PoniatowskiHead of Threat and Vulnerability Management