Most mTLS setups run on private PKI and won't notice any of this. The ones that will notice are the ones nobody wrote down. Somebody pointed a Postfix relay at the Let's Encrypt cert that was already on the box. A partner integration from four years ago asked for "a certificate from a trusted CA," so you sent them the one off your API gateway. An XMPP server has been authenticating to its federation peers with its web cert since before anyone on the current team was hired.
All of that worked because publicly trusted TLS certificates used to carry two extended key usages: serverAuth and clientAuth. The second one is going away. Not all at once, though. It goes one renewal at a time.
What changed
The Chrome Root Program has been pushing for years toward PKI hierarchies that do exactly one job. Its policy now says hierarchies in the Chrome Root Store have to be dedicated to TLS server authentication. Roots that also issue client auth, S/MIME, or code signing certs from the same tree are being phased out, and June 15, 2026 was the date by which leaf certificates from Chrome-trusted hierarchies were expected to be serverAuth-only. Chrome is right about this. When one hierarchy serves five purposes, a policy change for one of them drags the other four along, and the web PKI has been paying for that for a decade.
The CAs followed. Let's Encrypt announced in 2025 that it would drop clientAuth from its default profile. That landed in early 2026, and the temporary opt-in profile for stragglers was retired before Chrome's deadline. DigiCert, Sectigo, and the rest published their own cutoffs, mostly between late 2025 and mid-2026. Amazon Trust Services is Chrome-trusted too, so ACM public certificates went the same way. If you've been exporting ACM public certs to use elsewhere, look at what EKUs the recent ones actually carry.
The date matters less than how the change rolls out. Nobody revoked anything. A cert issued in April 2026 with both EKUs is still valid, still has both EKUs, and still works as a client certificate until it expires. With the current 200-day maximum lifetime, some of those will be in service into early 2027. So things break one cert at a time, each on its own renewal date, on a schedule nobody planned.
Who actually relied on clientAuth
Here's where I'd look, most likely first.
SMTP server-to-server
MTAs present a certificate on outbound connections, and lots of admins configure Postfix or Exim to present the same cert they use for inbound STARTTLS. Most receiving MTAs don't verify client certs, so usually nothing happens. The exceptions are relays that authenticate senders by certificate and receivers set to require and verify one. Those break.
XMPP federation
XMPP server-to-server auth can use certificates via SASL EXTERNAL (RFC 6120, with XEP-0178 covering the certificate handling). Prosody and ejabberd deployments routinely use Let's Encrypt certs for both directions of s2s. A peer that validates the cert and gets a serverAuth-only one on an outbound connection will either reject it or fall back to dialback, depending on config.
Partner B2B APIs
This is the one that hurts. A partner wants mutual TLS. You don't want to run a CA, they don't want to trust yours, and "just use a public cert" makes everyone happy. Then your cert renews, their verifier checks EKU (most TLS stacks do by default when validating a client cert), and clientAuth isn't there anymore.
Payment and banking integrations
Some financial networks and bank APIs specified publicly trusted client certs. A few run their own PKI or use industry hierarchies like the X9 Financial PKI. The rest were quietly leaning on the web PKI and now have to change.
Anything reusing the server cert because it was there
Service meshes bootstrapped in a hurry. Internal services calling each other with whatever was in the secrets store. IoT backends. A monitoring agent authenticating to its collector. I've seen the same wildcard cert mounted into forty pods, and nobody could tell me which pods used it as a server cert, which used it as a client cert, and which just had it lying around.
What the failure looks like
This part is miserable to debug, so here's exactly how it plays out.
The renewal succeeds. certbot exits zero, ACM says issued, your expiry dashboard goes green. No CA throws an error, because from the CA's side nothing went wrong. You asked for a TLS server certificate and you got one.
Then nothing happens for a while, because the new cert usually isn't live yet. Deploy pipelines, reload schedules, and secrets sync can put days or weeks between issuance and the first handshake where the new cert gets presented as a client cert. If the process only reads certs on restart, you're waiting for the next deploy.
When it finally breaks, the error shows up on the far side of the connection and points at the far side. Your logs show a handshake failure to the partner's hostname. The alert you get back is usually "bad certificate" or "unsupported certificate," which reads like their problem. The real reason sits in the peer's logs, which you probably can't see. OpenSSL-based verifiers log "unsupported certificate purpose." Go says the certificate "specifies an incompatible key usage." Java complains that the extended key usage doesn't permit TLS client authentication. Postfix logs a verification failure with the purpose error attached.
So the ticket reads "Partner X API down since Tuesday." Someone spends the first hour on their endpoint, their cert, their status page. By the time anyone checks the EKU on your client cert, the morning's gone. If the partner noticed first, you've also spent some goodwill.
Finding exposure before renewal does it for you
The goal: find every place a publicly issued cert gets presented as a client certificate, before its next renewal.
Check EKUs on your current inventory
Start with what you've got. Every cert in ACM, Key Vault, GCP Certificate Manager, and on disk has an EKU extension you can read. ACM's certificate description lists them, and any x509 dump shows them. Sort everything into three buckets: serverAuth only, public-CA certs with serverAuth plus clientAuth, and private CA certs. The middle bucket is where the risk is, and it shrinks with every renewal. Each cert that leaves it that way is one you should have checked before it left.
The inventory shows you which certs could be used as client certs. It can't tell you which ones actually are. That's what the next two steps are for.
Search handshake logs for certs presented as client certificates
Inbound first. Look at whatever terminates mTLS: nginx, Envoy, HAProxy, your cloud load balancer. You want client certs issued by a public CA. If your ingress logs the client cert's subject and issuer DN (most can, few do out of the box), that's one query. If it doesn't, turn it on today. Some partner may be sending you a public cert that's about to lose clientAuth, and your verifier will be the one rejecting it.
Outbound is harder because clients rarely log what they presented. Read config instead. Grep your config management, Helm values, and Terraform for client cert settings: Postfix's smtp_tls_cert_file, XMPP s2s cert options, HTTP client TLS configs, SDK mTLS options. Follow each path back to its source. If it's the same path as your server cert, or the secret name has "letsencrypt," "acm," or a public wildcard domain in it, you've got one.
Ask partners what they validate
Everyone skips this, and it's the step that matters most. Your cert is what changes, but their verifier decides whether anything breaks. Ask each mTLS partner:
- Do you validate against a CA bundle, pin a specific intermediate, or pin the leaf fingerprint?
- Does your verifier enforce EKU? (If they don't know, assume yes. That's the library default.)
- Do you match on subject DN, a SAN, or something else?
- How much lead time do you need to trust a new CA?
A partner pinning the leaf fingerprint doesn't care about EKU, but they break on every renewal anyway. Different problem, same phone call. A partner validating against the public root store with EKU enforcement has a hard deadline: your next renewal.
Where to go instead
Private CA for client identities
Client auth belongs on a PKI you control. Pick one:
- step-ca from Smallstep if you want self-hosted and light. It speaks ACME, so your existing automation carries over. This is what I'd reach for first.
- AWS Private CA if you live in AWS and want it managed. Watch the price: general-purpose mode is $400 per CA per month, short-lived mode is $50. Short-lived mode fits client certs well if your rotation keeps up.
- Vault's PKI secrets engine if you already run Vault and want issuance tied to its auth methods.
None of this is free. You now own a root, its key protection, and its distribution, and every verifier that needs that root has to get it. Internally, that's a config change. With external partners, it's a negotiation.
Separate server and client lifecycles
Even if one cert could technically do both jobs, don't let it. Server certs live under public CA rules: DCV, CT logging, lifetimes dropping to 100 days in March 2027 and 47 days in 2029. Client certs live under your rules. Tie them together and every public PKI policy change turns into a client-auth incident, and there will be more of those. Give each client identity its own cert, its own issuer, and its own renewal job.
Start the trust-anchor conversation with partners now
For each partner in the risky bucket, the ask is: "We're moving our client certificate to our own CA. Here's the root and intermediate. Can you add them to your trust store next to the current one by date X?" Keep it additive. Run both anchors for an overlap window, switch your client, confirm it works, then ask them to drop the old one. Banks and payment processors can take weeks or months and need a change ticket on their end, so call them first. If a partner insists on a publicly trusted client cert, ask which hierarchy they mean. An industry PKI or a CA product outside the Chrome-trusted tree might work. "Keep renewing the web cert and hope" won't.
Alert on EKU drift
This goes well beyond clientAuth. Expiry isn't the only thing that can change at renewal. EKUs, key algorithm, key size, issuing intermediate, and SANs can all shift when a CA updates its profile, and CAs will keep updating profiles as lifetimes shrink. A renewal that goes from serverAuth plus clientAuth to serverAuth only should page someone, same as a cert crossing the 14-day line.
Whatever holds your cert inventory should store EKUs per certificate and diff them on every renewal. We built CertPulse to pull ACM, Key Vault, GCP, and external endpoints into one view, and once everything's in one place, diffing properties across renewals is trivial. A script and a cron job can do it too. The tooling doesn't matter. What matters is that you find out a cert just lost something your systems depend on before a partner finds out for you.
The short version
- Pull EKUs for every publicly issued cert and flag anything still carrying clientAuth.
- For each flagged cert, figure out whether anything actually presents it as a client cert. Check inbound handshake logs and outbound client configs.
- Contact every mTLS partner this quarter. Ask what they validate and how much lead time they need.
- Stand up a private CA for client identities. Move internal services first, since partners take longer.
- Put EKU change detection next to your expiry alerts. The next CA profile change won't warn you either.
This is why we built CertPulse
CertPulse connects to your AWS, Azure, and GCP accounts, enumerates every certificate, monitors your external endpoints, and watches Certificate Transparency logs. One dashboard for every cert. Alerts when auto-renewal fails. Alerts when certs approach expiry. Alerts when someone issues a cert for your domain that you didn't request.
If you're looking for complete certificate visibility without maintaining scripts, we can get you there in about 5 minutes.