Eclipse Milo OPC UA Flaws: Why 0.6.x Users Face a Migration, Not a Patch

CISA's 15 October advisory lists six flaws in Eclipse Milo, the Java OPC UA library inside many gateways. The fix shipped in July, and 0.6.x gets none. Here's how to find Milo, harden it now and decid

Technical Solutions Architect
Published
Reading time
7 min read

On 15 October 2026, CISA published advisory ICSA-26-288-01 covering six vulnerabilities in Eclipse Milo, the open-source Java implementation of OPC UA. The highest score is CVSS v4.0 9.1 (Critical). The worst cases let an attacker recover user credentials, run methods they should not be allowed to run, delete protected nodes, or stop the server responding to every client.

Most news coverage stops at "upgrade to 1.1.5". That advice is correct, but it hides the hard part. Many teams cannot say whether they run Milo at all. If they do, the version they run may be one that no patch will ever reach. This post is about those two problems, plus a few configuration changes that reduce your exposure whatever version you are on.

What the advisory actually says

There are six CVEs, split across two version ranges:

  • Milo 0.6.0 through 1.1.4 are affected by CVE-2026-63252 (memory exhaustion from partial message chunks left behind when a client disconnects), CVE-2026-63248 (diagnostics nodes without authorization checks) and CVE-2026-60007 (a padding oracle on encrypted username tokens).
  • Milo 1.0.0 through 1.1.4 are also affected by CVE-2026-62927 (a denied method runs if it is batched with an allowed one), CVE-2026-58080 (copying the server config drops the RoleMapper, so role checks are skipped) and CVE-2026-61387 (deeply nested event filters exhaust the monitored-item quota for all clients until restart).

CVE-2026-60007 is the one with the 9.1 score. An attacker positioned on the network path who captures a username token encrypted under the Basic128Rsa15 policy can send repeated ActivateSession requests. The server's distinguishable errors act as a padding oracle, which lets the attacker recover the password and log in as that user.

One small inconsistency: the advisory's header box says "5 Vulnerabilities", but its list contains six CVE identifiers. The six listed are the ones to work from. The advisory does not say whether any of them are being exploited.

CISA lists the affected sectors as chemical, critical manufacturing, energy, and water and wastewater, with deployments worldwide. The researcher credited is Abhinav Agarwal.

The fix shipped three months before the advisory

The project published Milo 1.1.5 to Maven Central on 16 July 2026. Its release notes include "Close username-token padding oracle", "Restrict Call dispatch to authorized methods", "Restrict session security diagnostics access", "Preserve role mappings when copying server config", "Release pending UASC chunks on teardown" and "Make monitored-item quota exception-safe". Those entries line up with the six CVEs. Since then 1.1.6 (22 July), 1.1.7 (9 September) and 1.1.8 (6 October) have followed, and a 1.2.0 release candidate appeared on 12 October.

So any team that tracked the library's releases could have been patched since mid-July. A team that only reacts to CVE feeds or CISA advisories heard about it in mid-October. A three-month gap between a fix and the public advisory is normal for coordinated disclosure, and it is reasonable behaviour by the project. But it means "we patch when a CVE appears" puts you a quarter behind anyone who reads release notes for the handful of libraries that sit on a network boundary.

The 0.6.x trap

This is the part I would worry about most. The advisory states that no 0.6.x release contains the fixes. Teams on 0.6.x have to migrate to 1.1.5 or later.

The last 0.6.x release, 0.6.16, went to Maven Central on 21 April 2025. Milo 1.0.0 followed on 19 May 2025, and the Eclipse project page describes it as a "major release (API breakage)". Code written against 0.6 will not compile against 1.x as-is. Anything that touches the server's address space, node managers or subscription handling needs real engineering time and a proper test cycle. A version bump will not do it.

Three of the six CVEs reach back to 0.6.0. That includes the memory-exhaustion bug, which an unauthenticated remote client can use to take a server down, and the padding oracle. A gateway on 0.6.x is therefore exposed, and the only remedy is a migration project. Treat that as a planning decision. The question is whether you migrate this quarter, isolate the server until you can, or replace the component.

The artifact names also changed between the two lines, which matters when you search for Milo:

  • 0.6.x artifacts are published as org.eclipse.milo:sdk-server, sdk-client, stack-core and similar.
  • 1.x artifacts are published as org.eclipse.milo:milo-sdk-server, milo-sdk-client, milo-stack-core and similar.

A dependency search for milo-sdk-server will miss every 0.6 installation, and those are the ones you most need to find. Search on the group ID org.eclipse.milo and on jar names containing milo or starting with stack- and sdk-.

Where Milo hides

Milo is a library. Nobody installs it on purpose as a product, so it rarely appears in an asset register. Places I would look:

  • In-house Java services that read from PLCs or expose data over OPC UA: collectors, protocol bridges, historians, small "OPC UA to MQTT" services written by one engineer three years ago.
  • Integration frameworks. Apache Camel has a Milo component (camel-milo). Camel's issue tracker shows it moving from Milo 0.3.7 to 0.6.6 in 2022 (CAMEL-18144, Camel 3.18.0). Any Camel route using milo-server: or milo-client: pulls in whichever Milo version that Camel release bundles.
  • Vendor software and appliances built on the JVM. The advisory warns that because Milo is embedded in other products, the library version alone does not settle whether a product is exposed. You need the vendor's statement, so ask for one in writing.
  • Test rigs and simulators that were never meant for production but ended up on the plant network anyway.

Also check whether you run Milo as a server or a client. Every CVE in this advisory, as described, concerns server-side code: the Call service, server transport handlers, server configuration, diagnostics nodes, server-side username-token processing and monitored-item quotas. A pure client that connects out to a PLC's OPC UA server is a lower priority than a gateway exposing its own OPC UA endpoint to the network. That is my reading of the CVE descriptions. Confirm it for your own build before you lower anything's priority.

Configuration that helps regardless of version

You can make some changes this week, before any upgrade is scheduled. They reduce what an attacker can reach.

  • Remove Basic128Rsa15 from every endpoint. The padding oracle depends on username tokens encrypted under this policy. The policy is deprecated in the OPC UA specification, and commercial SDK documentation such as Prosys's Java SDK says it should be disabled by default. If a legacy client still needs it, write that down as a known exception with an owner and an end date.
  • Remove None/None endpoints and anonymous access on anything outside a lab. CVE-2026-63248 lets an anonymous client enable diagnostics over a None/None endpoint. CVE-2026-58080 and CVE-2026-62927 are worst where anonymous sessions are allowed. Many servers have both turned on only because the commissioning engineer needed a quick connection test.
  • Check that roles actually take effect. CVE-2026-58080 means a server built with OpcUaServerConfig.copy() silently loses its RoleMapper. Once you are on 1.1.5 or later, log in as a low-privilege user and try a protected method. A permission model you have never tested is an assumption, not a control.
  • Restrict who can reach port 4840 (or whatever you use). CISA's standard guidance applies: keep control system endpoints off the internet, behind firewalls, separated from business networks. In practice: an allow-list of client addresses at the network layer, so an unauthenticated memory-exhaustion attack can only come from hosts you already trust.

If you sell connected products into the EU

The EU Cyber Resilience Act's reporting obligations under Article 14 have applied since 11 September 2026. If you manufacture a product with digital elements and become aware of an actively exploited vulnerability in it, you must send an early warning to the relevant CSIRT and ENISA through the single reporting platform within 24 hours of becoming aware. A fuller notification is due within 72 hours.

The Milo advisory does not report exploitation, so the advisory on its own does not start that clock. But it is a fair test of whether you could meet the deadline if it did. If it took you more than a day to work out which of your shipped products embed Milo, and at which version, you could not have met a 24-hour deadline. The inventory you build this month is the same one you will need on the day a component in your product is exploited.

A drill for this month

Here is what I would do in the next two to four weeks:

  1. Search. Look across your source repos, build files and deployed jar directories for org.eclipse.milo, and include the 0.6-era artifact names. If you generate SBOMs, query them. If you do not, this is a cheap reason to start.
  2. Classify each hit. Record the version (0.6.x, 1.0–1.1.4, or 1.1.5+), the role (server or client), the exposure (which networks can reach it) and an owner.
  3. Ask your vendors. For every JVM-based OPC UA product, ask in writing whether it embeds Milo, which version, and when a fixed release ships. Record the date you asked and the answer.
  4. Harden now. Disable Basic128Rsa15, None/None and anonymous access where you can, and put network allow-lists in front of every Milo server.
  5. Upgrade the 1.x line. Moving from 1.0–1.1.4 to the current 1.x release should be a routine dependency update with a regression run.
  6. Decide on each 0.6.x instance. For each one, choose migrate, isolate or replace, give the decision an owner and a date, and do not leave it open.
  7. Fix the watch process. For the few libraries that terminate network protocols in your estate (OPC UA, MQTT, Modbus/TCP, TLS), subscribe to their GitHub releases, not just CVE feeds. July's release notes said "padding oracle" in plain words.

None of this is exotic. The work that takes the time is the inventory and the 0.6 decisions, and an advisory with clear version ranges is a good occasion to do both.

Sources


Finding the libraries you didn't know you shipped is the first week of a two-week discovery and audit sprint; if you'd like a hand with yours, book a discovery call.

Written by Navil Shah

I help teams that build connected products get their telemetry, edge and cloud layers into shape — including what the CRA and Data Act now expect of them.