Ask most controls engineers whether their OPC UA connections are secure, and they’ll say yes. Ask them to pull up the actual security policy on every endpoint in the cell, and you’ll usually find at least one PLC, historian bridge, or third-party gateway sitting on Security Policy: None — because that’s what worked during commissioning, and nobody went back to change it. This isn’t a hypothetical. It’s the single most common finding showing up in IEC 62443-4-1 assessments and OT hardening reviews right now, and it’s the kind of thing that used to get waved through when auditors were reviewing architecture diagrams instead of live configs. That’s no longer the case. Auditors are logging into servers and checking endpoint properties directly.
The good news: this is fixable in an afternoon per server, not a multi-quarter re-architecture. The bad news: it requires touching certificate trust stores, which is exactly the kind of maintenance work that gets skipped because it’s tedious and easy to defer. Here’s how to audit what you actually have, fix it properly, and prove it holds up when a cert expires mid-shift instead of during a change window.
Step 1: Find out what you’re actually running, not what you think you’re running
Every OPC UA server exposes its supported endpoints through the discovery service, and every serious client tool — UaExpert, the open-source stacks, or whatever your MES/SCADA vendor bundles — can enumerate them. Connect to each server’s discovery endpoint and list every combination of security policy (None, Basic256Sha256, Aes128_Sha256_RsaOaep, Aes256_Sha256_RsaPss) and security mode (None, Sign, SignAndEncrypt) it advertises.
The gotcha here is that servers frequently advertise multiple endpoints simultaneously — a properly configured Sign & Encrypt endpoint alongside a legacy None endpoint left enabled “just in case a client can’t negotiate.” That second endpoint is the actual risk. A client library that supports it will happily connect to whichever endpoint requires the least negotiation, and unless you’ve explicitly disabled the insecure one on the server side, nothing stops a misconfigured or older client from falling back to it silently. Auditors know this pattern and check for it specifically — it’s not enough to prove your MES client connects securely, you have to prove the insecure endpoint isn’t reachable at all.
What to check on the client side too
Don’t stop at servers. Pull the client-side configuration for every OPC UA consumer — MES connectors, historian collectors, SCADA gateways — and confirm each one is configured to require a minimum security mode rather than merely prefer one. Most client SDKs default to “connect to best available” behavior, which means a client will downgrade gracefully to None if that’s all a server offers, and log it as a routine informational message you’ll never notice unless you’re grepping for it.
Step 2: Turn off None. Actually turn it off.
On the server, disable any endpoint advertising Security Mode: None outright — don’t just deprioritize it. Most industrial OPC UA stacks (the commercial SDKs from vendors like Unified Automation and the open-source implementations built on the OPC Foundation stack) let you configure which endpoints are exposed independently of which ones are “recommended.” Recommended isn’t enforced. Exposed is what matters.
Set the floor at Sign & Encrypt with a modern security policy — Basic256Sha256 at minimum, moving to the Aes256_Sha256_RsaPss profile where your servers and clients support it. Sign-only (message signing without encryption) is better than nothing but leaves payloads readable on the wire, which matters more than people assume once you remember how much OPC UA traffic carries recipe parameters, setpoints, and quality data that shouldn’t be sitting in plaintext on a flat network segment.
Step 3: Build a real certificate trust chain — not a folder of self-signed certs
This is where most implementations quietly fail even after security mode is set correctly. OPC UA’s security model is only as good as your certificate handling, and the default behavior in a lot of commissioning workflows is to generate a self-signed certificate on first run and click “trust” on whatever the other end presents. That’s functionally equivalent to no authentication at all — you’ve encrypted the channel but you have no actual assurance about who’s on the other end of it.
Done right, certificate handling looks like this:
- Stand up an internal CA for OT — a proper root/intermediate structure, not necessarily tied to your enterprise PKI, but managed with the same discipline. Most plants use a dedicated OT certificate authority rather than routing through corporate IT’s public-facing CA, for both network segmentation and lifecycle-ownership reasons.
- Issue certificates per device or per application instance, following the OPC UA application instance certificate model, with the application URI correctly embedded — a common failure mode is copying one certificate across multiple server instances, which breaks the whole point of instance-level trust.
- Populate the trust list explicitly on every server and client — the CA certificate and any intermediate, not a hand-picked list of peer certificates. Explicit peer-to-peer trust lists work for small, static topologies but become unmanageable and get stale fast in anything larger.
- Set certificate lifetimes deliberately. Shorter-lived certs are better security practice but only if you have a rotation process that doesn’t depend on someone remembering. Longer-lived certs reduce operational risk of expiry but sit as a bigger liability if a private key is ever compromised. There’s no universally correct number here — pick a lifetime your team can actually operationalize and document why.
Step 4: Test what happens when a cert expires mid-shift
This is the step almost nobody does, and it’s the one that separates a real hardening effort from a checkbox exercise. An expired certificate shouldn’t silently drop the secure channel and fall back to an insecure one — but depending on your stack’s configuration, that’s exactly what can happen if a fallback endpoint still exists, or if the client is configured to retry with relaxed security on connection failure.
In a maintenance window, deliberately let a non-production certificate expire (or revoke it) while a client connection is active, and observe the actual failure behavior:
- Does the connection drop cleanly with a clear alarm, or does it silently reconnect on a weaker policy?
- Does your MES or SCADA layer surface the failure to an operator, or does data just stop updating with no visible error?
- Is there a defined process — and an on-call path — for issuing a replacement certificate without a multi-day IT ticket cycle?
If the answer to any of those is “we’re not sure,” that’s your actual finding, and it’s worth fixing before an auditor — or a production outage — finds it for you.
What “done right” actually looks like
A defensible OPC UA security posture means: no endpoint anywhere in the plant advertises Security Mode: None, every certificate traces to a managed CA with documented lifetimes, trust lists are built on CA trust rather than ad hoc peer approval, and you’ve actually watched a certificate expiration fail safely instead of assuming it will. That’s a concrete, auditable state — and increasingly, it’s the exact state IEC 62443-4-1 reviewers are asking you to demonstrate, not describe.
This article was written with the assistance of artificial intelligence. While we aim for accuracy, the information may be incomplete, out of date, or incorrect, and should be independently verified before you rely on it for any decision. It is provided for general information only and does not constitute professional advice.
