CVE-2026-63252 Overview
CVE-2026-63252 is a memory leak vulnerability in Eclipse Milo, an open-source implementation of the OPC Unified Architecture (OPC UA) protocol stack. The flaw affects Eclipse Milo versions 0.6.0 through 1.1.4. UASC (UA Secure Conversation) server transport handlers fail to release retained partial message chunks when a channel disconnects. A remote unauthenticated attacker can repeatedly send incomplete chunks and disconnect, exhausting pooled direct memory and terminating the server. The vulnerability is classified under CWE-401: Missing Release of Memory after Effective Lifetime.
Critical Impact
Remote unauthenticated attackers can trigger denial of service against OPC UA servers by exhausting pooled direct memory, disrupting industrial control system communications.
Affected Products
- Eclipse Milo 0.6.0 through 1.1.4
- OPC UA server implementations built on Eclipse Milo UASC transport
- Industrial and IoT applications depending on eclipse:milo
Discovery Timeline
- 2026-08-04 - CVE-2026-63252 published to NVD
- 2026-08-05 - Last updated in NVD database
Technical Details for CVE-2026-63252
Vulnerability Analysis
The vulnerability resides in the UASC server transport layer of Eclipse Milo. OPC UA messages are transmitted as sequences of chunks that the server accumulates in pooled ByteBuf direct memory buffers until a complete message is assembled. When a client disconnects mid-transmission, the server's chunk accumulator retains references to the partial chunks instead of releasing them back to the Netty allocator pool.
An attacker exploits this by opening a TCP connection to the OPC UA endpoint, sending one or more incomplete UASC message chunks, then abruptly disconnecting. Each iteration leaks direct memory. Because Netty's pooled direct memory is finite and typically bounded by the JVM -XX:MaxDirectMemorySize setting, repeated disconnects exhaust the pool and cause OutOfMemoryError, terminating the server process.
Root Cause
The root cause is a missing cleanup path in the chunk decoding pipeline. The ChunkDecoder and associated UASC server handlers did not iterate pending chunks on channel teardown to invoke ReferenceCountUtil.release() on each retained ByteBuf. Netty's reference-counted buffers only return to the pool when their refcount reaches zero, so orphaned references persist for the lifetime of the JVM.
Attack Vector
The attack requires only network reachability to a UASC endpoint. No authentication, user interaction, or session establishment beyond the initial Hello/OpenSecureChannel handshake is required. An attacker scripts a loop that connects, transmits a message header claiming a larger payload than will be sent, writes a partial chunk, and closes the socket.
// Patch: ChunkBufferAccumulator releases retained chunks on teardown
// Source: https://github.com/eclipse-milo/milo/commit/459715793ec54b0f33367a14f94264500a0d872b
package org.eclipse.milo.opcua.stack.transport.server.uasc;
import io.netty.buffer.ByteBuf;
import io.netty.util.ReferenceCountUtil;
import java.util.ArrayList;
import java.util.List;
final class ChunkBufferAccumulator {
private final int initialCapacity;
private List<ByteBuf> chunkBuffers;
ChunkBufferAccumulator() {
this(0);
}
ChunkBufferAccumulator(int initialCapacity) {
this.initialCapacity = initialCapacity;
}
// release() iterates chunkBuffers and calls ReferenceCountUtil.release on teardown
}
Source: Eclipse Milo commit 4597157
Detection Methods for CVE-2026-63252
Indicators of Compromise
- Repeated short-lived TCP connections to OPC UA port 4840 (or configured UASC port) from a single source that terminate before completing a full message
- Rising Netty pooled direct memory usage without a corresponding increase in legitimate client sessions
- JVM logs reporting io.netty.util.internal.OutOfDirectMemoryError or OutOfMemoryError: Direct buffer memory
- Server process crashes or restarts correlated with bursts of incomplete UASC handshakes
Detection Strategies
- Monitor OPC UA server JVM heap and direct memory metrics for sustained growth without release after client disconnects
- Alert on high connection-churn rates against UASC endpoints, especially from single IP addresses sending partial payloads
- Inspect application logs for repeated OpenSecureChannel failures or truncated chunk exceptions from ChunkDecoder
Monitoring Recommendations
- Collect Netty allocator metrics (PooledByteBufAllocatorMetric) and expose via JMX or Prometheus
- Deploy network flow monitoring on industrial control network segments hosting OPC UA endpoints
- Correlate server crash events with upstream firewall or IDS logs for connection-pattern analysis
How to Mitigate CVE-2026-63252
Immediate Actions Required
- Upgrade Eclipse Milo to a fixed release (post-1.1.4) that includes commit 4597157 from PR #1800
- Restrict network access to OPC UA endpoints to trusted management and OT VLANs using firewall rules
- Cap JVM direct memory via -XX:MaxDirectMemorySize and configure the process supervisor to restart on OOM to reduce downtime
Patch Information
The fix is committed to the Eclipse Milo repository as commit 459715793ec54b0f33367a14f94264500a0d872b titled "Release pending UASC chunks on teardown (#1800)." The patch introduces a ChunkBufferAccumulator class that tracks pending ByteBuf chunks and invokes ReferenceCountUtil.release() on all retained buffers when the channel is torn down. Additional coordination details are available in the Eclipse GitLab vulnerability report and the CVE assignment work item.
Workarounds
- Place OPC UA servers behind a reverse proxy or gateway that enforces per-source connection rate limits and message-completion timeouts
- Apply firewall rules that block untrusted networks from reaching UASC ports
- Enable network segmentation between IT and OT zones to reduce the reachable attacker surface
- Configure aggressive TCP idle and read timeouts on the server socket to close incomplete channels sooner
# Example: iptables rule limiting new connections to OPC UA port 4840
iptables -A INPUT -p tcp --dport 4840 -m conntrack --ctstate NEW \
-m limit --limit 20/minute --limit-burst 40 -j ACCEPT
iptables -A INPUT -p tcp --dport 4840 -j DROP
# JVM flags to bound and observe direct memory
java -XX:MaxDirectMemorySize=512m \
-Dio.netty.leakDetection.level=paranoid \
-jar milo-server.jar
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

