Skip to content

Community Registry Trust Model

The community registry lets Claudette discover and install third-party themes, plugins, and language grammars from utensils/claudette-community. Because installed extensions run inside Claudette — Lua plugins drive your SCM tab, grammars set how your code is highlighted — the bytes Claudette downloads have to be authenticated before they hit your disk.

This page describes the trust chain that protects that path.

The trust anchor: an embedded minisign public key

Section titled “The trust anchor: an embedded minisign public key”

Claudette ships with a minisign public key compiled directly into its binary. The matching secret key lives only in GitHub Actions Secrets on the claudette-community repository — it never leaves CI, and it’s never on a contributor’s machine.

The current key fingerprint is:

982022ABB1139C7B

The same public key bytes are also published in plaintext at keys/community-registry.pub for transparency, so you can compare what’s in claudette-community against what’s embedded in a Claudette release. The authoritative copy is the embedded one — the file in claudette-community is informational.

Every time you open the Community section of Settings or click Install, Claudette:

  1. Fetches registry.json and registry.json.sig in parallel from raw.githubusercontent.com/utensils/claudette-community/main/.
  2. Verifies that registry.json.sig is a valid minisign signature over registry.json produced by the embedded public key.
  3. Only then parses registry.json.
  4. When you click Install, downloads the contribution tarball from codeload.github.com/utensils/claudette-community/tar.gz/<commit-sha> — pinned to the commit SHA the verified registry attests to, never to a mutable branch ref.
  5. Recomputes the per-contribution content sha256 from the unpacked bytes and compares against the value in the verified registry.

If any step fails — missing signature, signature signed by a key Claudette doesn’t trust, content hash mismatch — the install is refused with a user-visible error and nothing is written to disk.

AttackMitigation
Maintainer’s GitHub account compromised; attacker pushes a malicious registry.jsonAttacker doesn’t have the signing key — the new file fails sig verification, no install
Network MITM (misconfigured CA, hostile WiFi, etc.) swaps registry bytesSame — sig won’t verify against the embedded key
Attacker rewrites the codeload tarball at <commit-sha> after publicationGitHub commit SHAs are immutable; rewriting them requires breaking SHA-1, and the secondary sha256 content hash gates the install regardless
Replay of an older signed registry to suppress a security updateMitigated partially — the older registry still pins each contribution to its sha256; revocation list (forthcoming, see issue #581) closes this fully
Tampering with registry.json.sig on the networkSig fails to decode or fails to verify; install refused
  • Compromise of the CI signing key itself. If the GitHub Actions secret leaks, an attacker can sign whatever they want. Mitigation: rotate the key (see below) and revoke compromised contributions. A proper transparency log (sigstore, etc.) is on the roadmap.
  • Malicious contributions submitted normally. The signature only attests that this is what the maintainers reviewed — not that what they reviewed is safe. PR review of new contributions is the human-in-the-loop gate.
  • revocations.json is not yet signed. The same gap that motivated this work exists for the revocation list. A follow-up PR will sign it the same way.

Rotation is coordinated across two repositories and one Claudette release:

  1. Generate a new keypair with minisign -G -W -p next.pub -s next.key (or rsign generate -W).
  2. Open a Claudette PR that adds next.pub alongside the current pubkey in src/community/trust/. The verifier accepts a signature from any embedded key.
  3. Release Claudette N+1 with both keys embedded. Wait for it to roll out to most users.
  4. Switch the CI signer by updating COMMUNITY_REGISTRY_MINISIGN_SECRET_KEY in claudette-community repo settings. The next push to main re-signs registry.json with the new key. Existing installations of Claudette N+1 keep working because both keys are accepted.
  5. Open a Claudette PR that removes the old key.
  6. Release Claudette N+2. Old key is gone; rotation complete.

Today there’s a single key. The verifier API takes a slice of public keys, so adding a second one is a one-line code change once you have the new .pub file.

If you want to confirm a published registry hasn’t been tampered with, install minisign and run:

Terminal window
curl -sLO https://raw.githubusercontent.com/utensils/claudette-community/main/registry.json
curl -sLO https://raw.githubusercontent.com/utensils/claudette-community/main/registry.json.sig
curl -sLO https://raw.githubusercontent.com/utensils/claudette-community/main/keys/community-registry.pub
minisign -V -p community-registry.pub -m registry.json -x registry.json.sig

Expected output:

Signature and comment signature verified
Trusted comment: claudette-community registry signed at <ISO-8601> for source.sha=<git-sha>

The trusted comment binds the signature to a specific commit SHA. You can confirm that SHA exists on main:

Terminal window
git ls-remote https://github.com/utensils/claudette-community.git main