Every SUNBURST binary that shipped in the SolarWinds Orion compromise passed signature verification. The certificate was valid. The chain checked out. Endpoint after endpoint installed the update precisely because it was signed by a trusted publisher — and that publisher's key was never stolen.
That last detail is the one worth sitting with. The attackers didn't crack a key or forge a certificate. According to the post-incident analysis, malware called Sunspot sat on the build server from around September 2019, watched for Orion build commands, and swapped malicious source into the compile step. The legitimate pipeline then did exactly what it was told: it built the tampered code and signed it with the real key. The certificate wasn't revoked until March 2021, and even then as cleanup, not because it had leaked.
So the uncomfortable thesis I want to argue: a signature proves who vouched for a set of bytes, not that those bytes are the ones your team wrote. If you're hardening code signing by locking down the key and calling it done, you've fortified the one link the SolarWinds attackers never touched.
What a signature actually asserts
A code signature is a narrow claim. It binds an identity — via a private key — to a specific artifact digest. Verification confirms two things: the bytes haven't changed since signing, and a key you trust produced the signature. That's genuinely useful. It's also the end of the sentence.
A signature answers "who vouched for these bytes?" It never answers "are these the bytes you meant to ship?"
The gap between those two questions is the entire supply-chain attack surface. Everything upstream of the signer — source control, dependency resolution, the build machine itself — can be corrupted, and the signer will happily notarize the result. Your key management can be flawless and your product still ships a backdoor.
Threat-model the pipeline, not the key
Look at where real incidents actually land, and a pattern emerges: attackers go after the long, soft chain between a commit and a signature, not the signature itself.
- Source. The 2024 XZ Utils backdoor was inserted by a contributor who spent roughly two years building maintainer trust before landing malicious code in a core compression library. No key involved — the poison went in at the source.
- Dependencies. Through 2025, widely used npm packages were hijacked via maintainer account takeovers, several traced to SMS-only MFA. The compromised package was published through legitimate credentials.
- Build. SolarWinds. The build host was the implant point, and signing laundered the result.
None of these are key-theft stories. Each one produced a correctly signed, correctly published artifact. So the design goal isn't "protect the key harder" — it's "shrink and observe the window between trusted source and trusted signature." Three controls do most of that work.
1. Remove the long-lived key entirely
A signing key sitting in a vault is a standing liability: a durable secret whose whole job is to be exfiltrated once. Keyless signing removes the asset. Sigstore's cosign generates an ephemeral keypair, authenticates the signer's OIDC identity — a CI workflow identity, for instance — to the Fulcio CA, and receives a short-lived certificate bound to that identity. The private key is used once and discarded; it never reaches Fulcio's servers. The signing event is then recorded in Rekor, an append-only public transparency log.
The security shift is structural. There's no persistent key to steal, and because every signature is logged, a rogue one is publicly detectable after the fact instead of invisible.
# Sign in CI — no stored key; identity comes from the OIDC token
cosign sign-blob --yes \
--output-signature app.sig --output-certificate app.pem \
./app-1.4.0.tar.gz
# Verify downstream — fail unless BOTH identity and issuer match
cosign verify-blob \
--certificate app.pem --signature app.sig \
--certificate-identity \
'https://github.com/acme/app/.github/workflows/release.yml@refs/tags/v1.4.0' \
--certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
./app-1.4.0.tar.gz
The verification side is where the real value lands. Pinning --certificate-identity and --certificate-oidc-issuer means you accept a signature only if it came from that workflow via that issuer. A signature produced by anything else — a laptop, a different repo, a stolen token from another provider — fails closed.
2. Isolate the signer from the build
Now re-read the SolarWinds mechanism as a control requirement: build steps must not be able to reach the signing credential, and one build must not be able to influence another. That is nearly the exact definition of SLSA Build Level 3 — hardened builds where user-defined build steps can't access signing secrets and runs are isolated from each other. Had the Orion build been unable to hand the signing key to arbitrary build-time code, Sunspot could still have tampered with the binary, but it couldn't have gotten it signed on the same box.
The practical move is to split the topology: the build job produces an unsigned artifact and hands it to a separate, minimal signing step that the build code can't reach into. On hosted CI, that's a distinct job with its own scoped OIDC identity — not a key exported into the build environment.
3. Sign provenance, and verify it on the way in
A signature over the artifact says nothing about how that artifact came to be. SLSA Build L2 adds signed provenance: a signed statement of which builder ran, from which source, over which inputs. L1 asks that provenance merely exist; L2 requires it be signed and authenticated downstream. Generate it in the pipeline, sign it the same keyless way, and — the part teams skip — actually verify it at consumption. Provenance nobody checks is documentation, not a control.
Fail-closed verification is the throughline: the signature must match a pinned identity and issuer, provenance must name the expected builder and source repo, and a missing or mismatched attestation blocks the deploy rather than logging a warning.
The takeaway
Run one test against your own pipeline: assume your signing key is perfectly safe, then ask whether a valid signature could still be produced over bytes your team never wrote. If the answer is yes — a build step can reach the key, nobody pins the signing identity on verify, or provenance is generated but never checked — then key protection was never your weak point, and the SolarWinds outcome is reachable with your key fully intact. Harden the pipeline that feeds the signer, and make consumption fail closed. A signature you don't verify against a pinned identity is a rubber stamp you handed to whoever compromised the build.
Sources: All You Need to Know About the SolarWinds Attack — The SSL Store, How X.509 Certificates Were Involved in the SolarWinds Attack — Keyfactor, SLSA Security Levels — slsa.dev, Sigstore Overview — docs.sigstore.dev