GitHub Advisoryadvisory · npm

GHSA-r2pf-9cw4-5j65 node-opcua: TCP Socket Leak (FIN-WAIT-2) via keepalive reconnection cycle - Resource Exhaustion

HIGH Published 2026-09-16 Modified 2026-09-16 Official page ↗
Aliases
CVE-2026-68904
Ecosystem
npm
Packages
node-opcua-transport, node-opcua-client, node-opcua
Severity
High
CVSS vector
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:H
Weaknesses
CWE-400
Reviewed
2026-09-16

Affected packages

• npm node-opcua-transport: >= 2.0.0, < 2.170.0 → fixed in 2.170.0 • npm node-opcua-client: >= 2.0.0, < 2.170.0 → fixed in 2.170.0 • npm node-opcua: >= 2.0.0, < 2.170.0 → fixed in 2.170.0

Description

SUMMARY ------- A combination of bugs in node-opcua causes unlimited TCP socket accumulation (FIN-WAIT-2 state) during automatic reconnection, leading to memory exhaustion and eventual container/process crash (OOM kill). The issue is triggered by the default configuration (keepSessionAlive: true) when the OPC UA server has clock skew relative to the client. Affected version: Tested on 2.169.0 (latest as of April 2026). ENVIRONMENT ----------- • Node.js: v24.11.0 • node-opcua: 2.169.0 • OS: Linux (containerized via Podman, slirp4netns networking) • OPC UA Server: Industrial PLC (opc.tcp endpoint), clock skew of ~50 minutes ahead of client • Client config: keepSessionAlive: true (default), keepAliveInterval: 3000, securityMode: None, securityPolicy: None ROOT CAUSE ANALYSIS ------------------- Bug #1 - ClientTCP_transport._on_ACK_response() uses socket.end() instead of socket.destroy() File: node-opcua-transport/src/client_tcp_transport.ts, _on_ACK_response() method When the HEL/ACK handshake fails during a reconnection attempt, the error handler calls socket.end(): if (err || !data) { externalCallback(err || new Error("no data")); if (this._socket) { this._socket.end(); // emit("failure") -> terminateConnection() -> forceConnectionBreak() This triggers a full transport-level reconnection on every keepalive cycle (every keepAliveInterval ms). Combined with Bug #1, each reconnection attempt leaks one TCP socket in FIN-WAIT-2. Impact amplification: With keepAliveInterval: 3000 (3 seconds), the client leaks ~20 sockets/minute, ~1200/hour, exhausting resources in hours. REPRODUCTION STEPS ------------------ 1. Set up an OPC UA server with a clock skewed more than the server's timestamp tolerance ahead of the client. 2. Connect using node-opcua with default settings (keepSessionAlive: true). 3. Monitor TCP sockets: ss -antp | grep FIN-WAIT-2 | wc -l 4. Observe FIN-WAIT-2 count growing continuously (approximately one per keepalive interval). 5. Eventually the process runs out of file descriptors or memory and crashes. SUGGESTED FIXES --------------- For Bug #1 (_on_ACK_response): // Replace socket.end() with socket.destroy() if (this._socket) { this._socket.destroy(); } For Bug #2 (_ping_server): Distinguish between transport-level errors (actual network outage) and application-level OPC UA status codes like BadInvalidTimestamp. The latter indicates the server is reachable and the session is alive - only the timestamp validation failed. The keepalive should not trigger reconnection. REPORTER -------- Marco Velluso @Velluso [email protected] Requesting CVE assignment and credit as reporter upon fix publication.

Related

Alias · CVE (1)

  • CVE-2026-68904 node-opcua is an OPC UA implementation for TypeScript and Node.js. vulnerability

Weakness · CWE (1)

  • CWE-400 Uncontrolled Resource Consumption weakness

References