fix: add VerifyTrustAnchor to gate manifest publisher trust (PILOT-243)#7
Conversation
…nst trusted-publisher list (PILOT-243) VerifySignature() in pkg/manifest/manifest.go only checked that the manifest signature is valid for the embedded publisher key — it did NOT verify that the publisher itself is trusted. An attacker could self-sign a manifest with their own key and it would pass. This commit: - Adds TrustedPublishers []string, a compile-time-embedded list of known-good publisher ed25519 public keys (fail-closed: empty list rejects all publishers). - Adds VerifyTrustAnchor() method that checks Store.Publisher against TrustedPublishers using bytes.Equal on the raw key bytes (encoding-agnostic). - Adds 5 tests: empty-list-fail-closed, untrusted rejection, trusted acceptance, multiple-key support, bad-format rejection. Callers should call VerifyTrustAnchor() after VerifySignature() to complete the trust chain: signature confirms integrity, trust anchor confirms the signer is known. Closes PILOT-243
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
🦾 Matthew PR Check — #7 PILOT-243Status
SummaryAdds CI Note
automated | matthew-pr-worker |
🦾 Matthew Explains — #7 PILOT-243What this doesAdds The gap// Before: signature check only
if !ed25519.Verify(pubKey, payload, sig) { return ErrInvalidSignature }
// Attacker can self-sign with any key → accepted
// After: trust anchor checked first
if err := m.VerifyTrustAnchor(trustedPublishers); err != nil { return err }
// Only keys in the allowlist passChanges
Risk: LOW
automated | matthew-pr-worker |
|
✅ Matthew Cleanup — PR #7 (PILOT-243) merged at 2026-05-29T20:53:46Z. Branch
|
✅ Matthew Merged Cleanup — #7 PILOT-243Merged by TeoSlayer at 2026-05-29 20:39 UTC Branch Action: Jira PILOT-243 → READY. VerifyTrustAnchor now gates manifest publisher trust against a compile-time allowlist of known publisher keys — fail-closed by default. Combined with VerifySignature, this closes the self-signing trust bypass. |
What failed
VerifySignature()inpkg/manifest/manifest.goonly checks that the manifest signature is cryptographically valid for the embedded publisher key — it does NOT verify that the publisher itself is a trusted party. An attacker can self-sign a manifest with their own ed25519 key and the signature check passes.Combined with the daemon IPC unauth verbs (PILOT-230–233), this means a malicious app-store package can self-sign, install, and run with full daemon privileges via the supervisor.
Why this fix
Adds
TrustedPublishers []string— a compile-time-embedded list of known-good publisher ed25519 public keys (fail-closed: empty list rejects all publishers). AddsVerifyTrustAnchor()method that checksStore.Publisheragainst the trusted list usingbytes.Equalon the raw key bytes (encoding-agnostic — accepts bothed25519:<base64>and raw base64 forms).Callers should call
VerifyTrustAnchor()afterVerifySignature():VerifySignature()→ _cryptographic_ integrity (the manifest wasn't tampered with)VerifyTrustAnchor()→ _trust_ confirmation (the signer is a known publisher)Verification
go build ./...— cleango vet ./...— cleango test ./... -count=1— all 5 packages pass, including 5 new trust-anchor tests:Diff stat
Closes PILOT-243