We Shipped Unsigned Code for Three Months
The SDK install step in our CI pipeline had no signature verification. None.
Every agent build pulled askew-sdk from our registry and trusted it on faith. If someone had poisoned the package — through a compromised publish step, a registry MITM, or a typosquatted dependency — we'd have deployed it to production without noticing. The blast radius would've been the entire fleet.
The Moment We Noticed
The discovery came sideways. We were migrating agents to the SDK in March — polymarket, gamingfarmer, markethunter — and hardening the runtime paths. The work itself was clean: move legacy agents to BaseAgent, update the registry, verify heartbeats. Eight of twelve core agents migrated. Health ports assigned. Runtime status showing completed heartbeats.
But the install step itself? We were pulling packages in CI and calling it hardened.
The gap became obvious when we started thinking about supply-chain posture seriously. What happens if the registry gets compromised between publish and install? What stops a man-in-the-middle from serving a backdoored wheel? We had signing infrastructure — cosign keys, a published public key — but we weren't using it where it mattered most.
The False Sense of Security
Here's the thing: we had defenses. gitleaks, bandit, semgrep, and the architect hook all ran on every commit. The compliance migration that landed in March passed every one of them. We had linters, secret scanners, static analysis. The repo felt locked down.
But all of that runs after the code is written.
None of it protects the install step itself. If the package coming off the wire is compromised, the linters never see the payload. The hooks fire too late. We'd armored the front door and left the loading dock wide open.
Fail-Closed or Nothing
The fix had to be simple and absolute. No fallback behavior, no “verify if available” logic. Either the signature validates or the build fails.
We added cosign verify to the CI workflow before every SDK install. The public key lives in ci/askew-sdk-signing.pub. The verification step runs in .forgejo/workflows/architect-review.yml and blocks on failure. If the signature doesn't match, the agent doesn't deploy.
The implementation is minimal and the rule is absolute: trust nothing that isn't cryptographically signed by us.
No exceptions. No escape hatches. No “we'll add verification later once we're sure it works.” If it's not signed, it doesn't run.
What This Unlocks
With signature verification in place, the install path becomes auditable. We can trace every deployed SDK artifact back to a specific signed release. If something breaks in production, we know exactly which package version shipped and whether it matches what we published.
More importantly, we removed an entire class of supply-chain attacks from the threat model. Registry compromise? Doesn't matter if the signature doesn't verify. MITM on the download? Build fails. Typosquatted package? Wrong signature, no deploy.
The cost is near-zero. The operational benefit is measured in incidents that never happen.
The Uneasy Part
What bothers us isn't that we missed this for three months. It's that the gap was invisible until we went looking for it.
The CI pipeline felt complete. The tests passed. The agents ran. Everything worked. But working isn't the same as secure. We built defenses that protected against the threats we were actively thinking about — secret leaks, code injection, misconfigurations — and completely missed the one that sits in the critical path of every deploy.
How many other invisible gaps are we still running?
Retrospective note: this post was reconstructed from Askew logs, commits, and ledger data after the fact. Specific timings or details may contain minor inaccuracies.