Community Registry Trust Model
The community registry lets Workbench discover and install third-party themes, plugins, and language grammars from utensils/workbench-community. Because installed extensions run inside Workbench — Lua plugins drive your SCM tab, grammars set how your code is highlighted — the bytes Workbench 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”Workbench ships with a minisign public key compiled directly into its binary. The matching secret key lives only in GitHub Actions Secrets on the workbench-community repository — it never leaves CI, and it’s never on a contributor’s machine.
The current key fingerprint is:
982022ABB1139C7BThe same public key bytes are also published in plaintext at keys/community-registry.pub for transparency, so you can compare what’s in workbench-community against what’s embedded in a Workbench release. The authoritative copy is the embedded one — the file in workbench-community is informational.
What gets verified, and when
Section titled “What gets verified, and when”Every time you open the Community section of Settings or click Install, Workbench:
- Fetches
registry.jsonandregistry.json.sigin parallel fromraw.githubusercontent.com/utensils/workbench-community/main/. - Verifies that
registry.json.sigis a valid minisign signature overregistry.jsonproduced by the embedded public key. - Only then parses
registry.json. - When you click Install, downloads the contribution tarball from
codeload.github.com/utensils/workbench-community/tar.gz/<commit-sha>— pinned to the commit SHA the verified registry attests to, never to a mutable branch ref. - Recomputes the per-contribution content
sha256from the unpacked bytes and compares against the value in the verified registry.
If any step fails — missing signature, signature signed by a key Workbench doesn’t trust, content hash mismatch — the install is refused with a user-visible error and nothing is written to disk.
What this protects against
Section titled “What this protects against”| Attack | Mitigation |
|---|---|
Maintainer’s GitHub account compromised; attacker pushes a malicious registry.json | Attacker doesn’t have the signing key — the new file fails sig verification, no install |
| Network MITM (misconfigured CA, hostile WiFi, etc.) swaps registry bytes | Same — sig won’t verify against the embedded key |
Attacker rewrites the codeload tarball at <commit-sha> after publication | GitHub 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 update | Mitigated 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 network | Sig fails to decode or fails to verify; install refused |
What this does NOT protect against (yet)
Section titled “What this does NOT protect against (yet)”- 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.jsonis 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.
Key rotation
Section titled “Key rotation”Rotation is coordinated across two repositories and one Workbench release:
- Generate a new keypair with
minisign -G -W -p next.pub -s next.key(orrsign generate -W). - Open a Workbench PR that adds
next.pubalongside the current pubkey insrc/community/trust/. The verifier accepts a signature from any embedded key. - Release Workbench N+1 with both keys embedded. Wait for it to roll out to most users.
- Switch the CI signer by updating
COMMUNITY_REGISTRY_MINISIGN_SECRET_KEYinworkbench-communityrepo settings. The next push tomainre-signsregistry.jsonwith the new key. Existing installations of Workbench N+1 keep working because both keys are accepted. - Open a Workbench PR that removes the old key.
- Release Workbench 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.
Verifying a published registry yourself
Section titled “Verifying a published registry yourself”If you want to confirm a published registry hasn’t been tampered with, install minisign and run:
curl -sLO https://raw.githubusercontent.com/utensils/workbench-community/main/registry.jsoncurl -sLO https://raw.githubusercontent.com/utensils/workbench-community/main/registry.json.sigcurl -sLO https://raw.githubusercontent.com/utensils/workbench-community/main/keys/community-registry.pubminisign -V -p community-registry.pub -m registry.json -x registry.json.sigExpected output:
Signature and comment signature verifiedTrusted comment: workbench-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:
git ls-remote https://github.com/utensils/workbench-community.git mainSee also
Section titled “See also”utensils/workbench-community/keys/README.md— the published pubkey + maintainer-side rotation procedure- Workbench issue #581 — the supply-chain audit that motivated this work
- Workbench issue #567 — the community registry TDD
Original source: utensils.io/claudette