BadCertificateRevocationUnknown
BadCRL
BadCertificateRevocationUnknown means the validator could not determine the revocation status of the peer certificate, almost always because no CRL for its issuing CA is present in the crl store. Export a current CRL from that CA and install it alongside the CA certificate.
What you actually see
A properly chained, in-date, correctly named certificate is refused with a revocation-related error, and the crl folder in your PKI is empty or holds an old file.
Why it happens
- No CRL is installed for the issuing CAValidation checks revocation status for the certificate, and with no CRL available for its issuer the result is unknown rather than good. OPC UA stacks do not treat unknown as acceptable by default. The crl subfolder next to the store holding the CA certificate is where the file must be.
- The installed CRL has expiredA CRL carries thisUpdate and nextUpdate. Past nextUpdate the file is stale and most validators discard it, which puts you back to unknown. CAs commonly publish CRLs with a validity of days, so a one-time manual copy quietly rots.
- The CRL does not match the CA certificate that signed the leafAfter a CA key rollover there are two CA certificates with the same subject and different keys. A CRL signed by the new key does not cover leaves issued under the old one. The CRL issuer and key identifier have to line up with the CA certificate in the store.
- The stack cannot fetch CRLs over the network and you assumed it wouldOPC UA validation uses locally provisioned CRLs. There is no requirement to follow the CRL Distribution Point URL in the certificate, and most stacks do not, particularly on isolated plant networks where the CDP host is unreachable anyway.
- Self-signed peers where revocation checking is still switched onA self-signed certificate has no CA and no CRL. Some configurations still demand a revocation answer for every certificate, so self-signed peers fail. The right setting is to require CRLs for CA-issued chains and accept that self-signed anchors are managed by trust-list membership alone.
How to fix it
In diagnostic order: work down, do not skip ahead.
- Confirm which CA needs a CRLRead the issuer of the failing certificate: openssl x509 -in peer.der -inform der -noout -issuer. That CA, and every CA above it in the chain, needs a current CRL. A missing CRL for a higher CA reports as BadCertificateIssuerRevocationUnknown instead.
- Export a current CRL from the CAOn an AD Certificate Services CA use certutil -CRL then take the .crl file from CertEnroll; from OpenSSL use openssl ca -gencrl -out ca.crl. Check the dates with openssl crl -in ca.crl -inform der -noout -text and confirm nextUpdate is in the future.
- Install it in the crl folder of the right storePlace it under the same store as the CA certificate: issuer/crl for intermediates held in the issuer store, trusted/crl for a root you trust directly. Both DER and PEM are usually accepted; keep the extension the stack expects, normally .crl.
- Reload and reconnectRestart the application or reload its trust list, then retry. If the error changes to a certificate or issuer revoked code, the CRL is now being read correctly and the certificate genuinely appears on it.
- Automate the refresh before the next nextUpdateSchedule a job that pulls the CRL from the CA and drops it into every PKI crl folder, or move the fleet onto a Global Discovery Server, which distributes trust lists and CRLs as a managed pair.
Where it shows up, by tool and stack
| Tool / stack | What to do there |
|---|---|
| UA-.NETStandard (C#) | The store directories each have a crl subfolder that is read at validation time. This error is suppressible via the CertificateValidation event, and some sample configurations disable revocation checking outright - a change worth reversing before production. |
| UaExpert | The certificate validation dialog names the revocation problem and lets you accept for the session. The permanent fix is to place the CRL into UaExpert's PKI issuer or trusted crl folder under the user profile. |
| open62541 (C) | UA_ClientConfig_setDefaultEncryption takes a revocationList argument. Passing an empty revocation list plus a CA-issued trust list is precisely the configuration that produces an unknown revocation status, so populate it with the CA's CRL. |
| node-opcua | The certificate manager expects CRL files in the crl subfolder of trusted or issuers. node-opcua will report a revocation status problem rather than silently accepting, so an empty crl folder is the first thing to check. |
| asyncua (Python) | Revocation material must be supplied locally to the validator. asyncua does not retrieve CRLs from a distribution point, so a CA-based deployment needs the CRL files managed as part of the deployment. |
| Ignition | Gateway certificate management has no built-in CRL fetch scheduler, so operators typically wire a scripted refresh. A CRL that expired over a weekend is a classic Monday-morning fleet-wide connection failure. |
What it looks like in the log
Certificate validation failed. Error: BadCertificateRevocationUnknown. No CRL found for issuer CN=Plant Sub CA 1
Revocation status could not be determined for CN=plc-01.plant.local: CRL store empty
Confirm the fix
Reconnect and confirm the session activates, then run openssl crl -in ca.crl -inform der -noout -lastupdate -nextupdate and confirm nextUpdate is comfortably in the future for every CA in the chain.
Stop it happening again
Publish CRLs with a validity long enough to survive an outage window, and distribute them automatically with the trust list so no PKI store ever holds a CA certificate without a current CRL beside it.
Stuck on more than one of these? The troubleshooting clinic works through broken configurations end to end, on camera.
Troubleshooting clinic →Last verified 7 September 2026 against OPC UA 1.05.07. OPC UA Connect is an educational resource and is not affiliated with the OPC Foundation.