The ugly version of this problem happens at 2 a.m., about four months from now. Someone pushes a point release of an internal menu-bar utility through Munki. It installs fine on the build Mac — the one with all the old certs still in its login keychain. It fails to launch on every field laptop with a Gatekeeper dialog nobody can read because the window closed before they finished the sentence. The on-call engineer spends an hour assuming it’s the MDM. It isn’t.
Here’s the thing worth internalising before the holidays swallow your December: the original Developer ID Certification Authority (the intermediate sub-CA) expires on February 1, 2027. Not a deprecation. Not a “we strongly encourage.” An expiration date baked into a certificate that Apple issued years ago and cannot un-issue. Any Developer ID certificate that chains through that old intermediate stops validating on that date, and everything signed with it — apps distributed outside the Mac App Store, .pkg installers, kernel extensions, command-line tools — goes with it.
Let me run the objections, because a colleague of mine raised all of them in about ninety seconds and most of them are the ones you’re already forming.
“Apple extends deadlines constantly. This’ll slip.”
It won’t, and the reason is technical rather than political. The things Apple extends are policies — the required-reason API enforcement, the notarisation grace periods, the “we’ll start rejecting this at some future submission.” Those live in Apple’s servers and Apple’s rules, and rules can be rewritten with a news post.
This is not that. The expiry is a field inside a certificate that was signed by Apple’s root years ago. The signature covers the expiry date. Change the date and the signature breaks; re-sign it and it’s a different certificate that nothing in the field trusts. There is no lever in Cupertino that pushes this out. When people say “cryptographically immutable” they usually mean “we’d rather not,” but here it’s the literal thing. A child certificate cannot be valid longer than the CA that issued it. February 1 arrives, the parent is dead, the children are dead, the end.
“Fine, but my certs don’t expire until 2029. I’m clear.”
This is the trap, and it’s a reasonable one to fall into. Your Developer ID leaf certificate has its own expiry, and if it reads 2029 you’ll feel safe. The question is not when your leaf expires — it’s which intermediate it chains through. A leaf issued before roughly early 2022 chains to the old Developer ID Certification Authority, and no matter what your leaf’s own date says, it inherits the parent’s death date.
That’s actually the logic behind Apple’s recommended filter. Log into Certificates, Identifiers & Profiles on developer.apple.com, look at your Developer ID Application and Developer ID Installer certificates, and flag anything expiring on or before February 1, 2027. Because Developer ID certs run about five years, a leaf expiring on or before that date is almost certainly a child of the doomed intermediate. Newer certs expire later because they chain through the current CA.
Don’t take the portal’s word as gospel, though. Check the actual chain on a binary you ship:
If you want to see the intermediate’s own validity window, pull the certs out and read them:
A notAfter of Feb 1 00:00:00 2027 GMT is the one that ends your weekend.
“I’ll just re-notarise the old builds and the staple fixes it.”
No. Notarisation and the signature are different animals. A stapled notarisation ticket says Apple scanned the binary and found nothing nasty — it does not vouch for the certificate chain at launch. Gatekeeper still walks the chain, still hits the dead intermediate, still refuses. You can re-notarise a binary signed with a resurrected-looking cert all you like; the launch-time trust evaluation is the part that fails, and that happens on the user’s Mac, offline, with no server you control in the loop.
The only fix is a new signature from a Developer ID certificate that chains through the current CA. That means: request fresh Developer ID Application and Developer ID Installer certificates from the portal, re-sign, re-notarise, re-staple, re-ship. For kernel extensions — if you’re still shipping a kext in 2026 you have other problems, but — same story, and the signature matters more there, not less.
“This is an ISV problem. We’re an IT shop, not a software vendor.”
This is the line I’d push back on hardest, because the enterprise exposure is worse, not lesser. Commercial vendors live and die by their signing pipeline; someone owns it, someone watches the expiry dashboard, someone gets paged. Internal IT signing infrastructure is where certificates go to be forgotten.
Think about what you actually ship to your own fleet. The onboarding app that sets up a new hire’s Mac. The VPN helper. The printer-config pkg. The little SwiftUI thing a departed engineer wrote in 2021 that half the finance team depends on. These get signed with a Developer ID cert, dropped into Jamf as a policy, or packaged into Munki, or pushed through a custom MDM InstallApplication workflow — and then nobody touches the signing identity for years because it Just Works. The build machine’s keychain has the old cert. CI has the old cert in a .p12 someone base64’d into a secret in 2022. It all keeps working right up until it doesn’t, and “doesn’t” is a fixed date on the calendar.
Go audit your pipeline specifically. Grep your build scripts for hardcoded identity strings:
If a GitHub Actions workflow imports a fixed .p12 and signs with a hardcoded Developer ID Application: … SHA or name, that pipeline will keep building green and keep producing binaries that are dead on arrival. Green build, dead artefact. That’s the part that chews up an afternoon — nothing errored. In Xcode, check your CODE_SIGN_IDENTITY and any manual signing in .xcconfig files; let it resolve to the new identity rather than a pinned expiring one, and rotate the stored credential in every CI secret store and keychain on every runner.
“How much of this is urgent versus theatre?”
Fair question, and the honest answer has a gradient. Apps you ship frequently will likely get re-signed with a current cert in the normal course of business before February — a routine release quietly fixes them, and you may never notice there was a problem. The danger lives entirely in the things that don’t get rebuilt: the stable internal utility, the archived installer in your self-service catalog, the rescue tool you keep around for exactly the kind of emergency where you cannot afford it to fail to launch. Those are frozen in time, signed once, trusted until February 1.
So the triage is simple. Everything on your fleet that was signed and shipped more than a year ago and hasn’t been rebuilt since: assume it’s a child of the dying CA until the chain proves otherwise. Pull the four audit commands above into a script, run it against your package repo and your Jamf/Munki catalog, and sort by intermediate. The ones chaining to the old authority get re-signed and re-shipped now, in October, while it’s a ticket and not an incident.
The deadline doesn’t negotiate and it doesn’t send a reminder. The only variable you control is whether you find the dead certs or your users do.
