You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(appstore): sign the catalogue and verify it fail-closed
Replace the placeholder catalogue trust anchor with a real embedded
ed25519 key (internal/catalogtrust, ldflags-overridable for rotation):
- pilotctl loadCatalogue fetches a detached <url>.sig and verifies it
against the embedded key before trusting any entry; unsigned, missing,
or tampered catalogues are refused.
- New 'pilotctl appstore sign-catalogue' writes the detached signature and
refuses to sign with a key that doesn't match the embedded public key.
- cmd/daemon passes the embedded key into appstore.Config.CatalogPubkey,
retiring the all-zeros placeholder at the wire-up point.
- Sign catalogue.json; document signing + key rotation in catalogue README.
Tests: catalogtrust verify (happy/tamper/short/no-key), signed-catalogue
load + fail-closed (missing sig, tamper).
To rotate: generate a new keypair, store the private key securely, update
94
+
the embedded public key (source default or `-ldflags`), and re-sign the
95
+
catalogue. `sign-catalogue` refuses to sign with a key that doesn't match
96
+
the embedded public key, so a mismatch is caught before publishing a dead
97
+
signature.
65
98
66
99
## Trust model
67
100
68
101
| Layer | Trust anchor | Verifies |
69
102
|---|---|---|
70
103
| User trusts pilotctl | Project release pipeline (signed pilotctl binary) | The catalogue URL is correct |
71
-
| pilotctl trusts the catalogue |Future: signed against `EmbeddedCatalogPubkey`; today: the raw URL itself | App IDs map to specific bundle URLs + SHAs |
104
+
| pilotctl trusts the catalogue |Detached ed25519 signature against the embedded catalogue key (`internal/catalogtrust`) | The app list (IDs → bundle URLs + SHAs) is authentic; a substituted catalogue is rejected|
72
105
| pilotctl trusts the bundle | Embedded `bundle_sha256` matches downloaded bytes | A CDN substitute is rejected |
73
106
| Daemon trusts the manifest | Embedded ed25519 publisher pubkey verifies the signature | The bundle's manifest hasn't been tampered with |
// Guard: refuse to sign with a key that doesn't match the embedded
181
+
// trust anchor — the resulting .sig would never verify in the wild.
182
+
embed:=catalogtrust.PublicKey()
183
+
ifembed==nil {
184
+
fatalHint("internal_error", "rebuild pilotctl with a valid embedded catalogue key", "embedded catalogue public key is missing/malformed")
185
+
}
186
+
if!bytes.Equal(pub, embed) {
187
+
fatalHint("invalid_argument",
188
+
"this key does not match the embedded catalogue public key; pilotctl would reject the signature. Use the release catalogue key, or rebuild pilotctl with -ldflags overriding catalogtrust.publicKeyB64",
0 commit comments