CVE-2026-42789 Overview
CVE-2026-42789 is an improper certificate chain of trust validation flaw [CWE-295] in the Erlang OTP public_key library, specifically in the pubkey_cert module. The defect lets a non-CA certificate be accepted as an intermediate issuer, enabling certificate chain forgery against any TLS or mTLS endpoint built on the OTP ssl application. An attacker holding any end-entity certificate issued by a trusted CA, where that certificate carries basicConstraints cA:false and no keyUsage extension, can sign forged leaf certificates for arbitrary identities. The forged chain passes public_key:pkix_path_validation/3, breaking both server identity verification on clients and client certificate verification on mTLS servers.
Critical Impact
Any holder of a leaf certificate from a trusted CA can impersonate arbitrary servers or clients across every Erlang/OTP TLS endpoint that relies on the default verifier.
Affected Products
- Erlang/OTP 17.0 through versions before OTP 26.2.5.21, 27.3.4.12, 28.5.0.1, and 29.0.1
- public_key application versions 0.22 through before 1.15.1.7, 1.17.1.3, 1.20.3.1, and 1.21.1
- Any application built on the OTP ssl stack that uses the default certificate verifier for TLS or mTLS
Discovery Timeline
- 2026-05-27 - CVE-2026-42789 published to NVD
- 2026-05-27 - Last updated in NVD database
Technical Details for CVE-2026-42789
Vulnerability Analysis
The vulnerability lives in lib/public_key/src/pubkey_cert.erl, inside pubkey_cert:validate_extensions/7. Two cooperating flaws break the chain-of-trust enforcement that X.509 path validation depends on.
First, the clause handling basicConstraints cA:false recurses into the remaining extensions instead of rejecting the certificate when it sits in the issuer position. A certificate that explicitly disclaims being a CA is still allowed to issue downstream certificates. Second, the keyUsage check only executes when the extension is present. A certificate that omits keyUsage entirely bypasses the keyCertSign enforcement that would otherwise block non-signing certificates from acting as issuers.
Together, the defects let public_key:pkix_path_validation/3 accept a chain where a leaf certificate signs another leaf certificate. The validator treats the forged path as trusted.
Root Cause
The root cause is missing rejection logic in the cA:false branch of validate_extensions/7 combined with conditional, presence-gated enforcement of keyUsage. RFC 5280 requires both basicConstraints cA:true and keyCertSign in keyUsage for any certificate used to verify other certificate signatures. The Erlang implementation enforced neither when the relevant extensions were absent or set permissively in issuer position.
Attack Vector
An attacker obtains any end-entity certificate from a CA in the victim's trust store, provided the certificate has basicConstraints cA:false and lacks keyUsage. Such certificates are common among older or minimally-profiled issuers. The attacker uses that certificate's private key to sign a forged leaf certificate for any identity, such as a target server hostname or a privileged client subject. The attacker presents the chain forged_leaf -> attacker_cert -> trusted_CA to an Erlang/OTP TLS peer. The default verifier accepts the chain, allowing the attacker to impersonate the target or authenticate as a forged client over mTLS.
No authentication or user interaction is required against the target. The attack is delivered over the network during the TLS handshake.
No verified public exploit code is available. See the GitHub Security Advisory GHSA-c99q-jmpx-v8qq and the CNA advisory for CVE-2026-42789 for full technical details.
Detection Methods for CVE-2026-42789
Indicators of Compromise
- TLS handshakes presenting certificate chains where an intermediate certificate carries basicConstraints cA:false or lacks the keyUsage extension
- Successful authentications to Erlang/OTP services using client certificates whose issuer is itself an end-entity certificate
- Unexpected leaf certificates for sensitive hostnames signed by issuers not normally observed in the environment's certificate transparency baseline
Detection Strategies
- Inspect captured TLS server and client certificate chains and flag any chain element other than the root that has cA:false or missing keyUsage:keyCertSign
- Audit Erlang/OTP application versions and the bundled public_key version using application:which_applications(). to identify unpatched deployments
- Correlate certificate fingerprints presented to Erlang services against certificate transparency logs to detect forged leaves issued outside legitimate workflows
Monitoring Recommendations
- Centralize TLS handshake telemetry from Erlang/OTP services and alert on anomalous issuer chains or new intermediate fingerprints
- Track changes to trust stores and CA bundles used by OTP applications, and monitor for certificate validation errors and overrides in application logs
- Baseline expected client certificate subjects on mTLS endpoints and alert on identities signed by previously unseen issuers
How to Mitigate CVE-2026-42789
Immediate Actions Required
- Upgrade Erlang/OTP to 26.2.5.21, 27.3.4.12, 28.5.0.1, or 29.0.1, matching your current major release branch
- Upgrade the standalone public_key application to 1.15.1.7, 1.17.1.3, 1.20.3.1, or 1.21.1 where it is managed independently of the OTP release
- Inventory every service that uses the OTP ssl application for TLS or mTLS and prioritize patching of internet-facing and identity-bearing endpoints
Patch Information
The Erlang/OTP team fixed the defect in pubkey_cert:validate_extensions/7 so that certificates with basicConstraints cA:false are rejected in issuer position and keyCertSign enforcement no longer depends on keyUsage being present. The fixes are tracked in OTP commit 471cd2f6 and OTP commit 59c8d82. Refer to the Erlang version order documentation when validating that an installed build is at or above the fixed version on its branch.
Workarounds
- Configure the OTP ssl options with a custom verify_fun that explicitly rejects any chain element with basicConstraints cA:false or missing keyUsage:keyCertSign
- Pin trusted issuers using cacertfile limited to known CAs that issue only properly profiled intermediates, reducing exposure until patching is complete
- Where feasible, restrict trust to internal PKI that issues intermediates with both cA:true and keyCertSign set, and remove third-party CAs that issue legacy end-entity certificates without keyUsage
# Verify installed OTP and public_key versions on a running node
erl -noshell -eval 'io:format("~p~n", [erlang:system_info(otp_release)]), application:load(public_key), {ok, V} = application:get_key(public_key, vsn), io:format("public_key ~s~n", [V]), halt().'
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.


