[VS-NfD] Add a plugin allowlist with SHA-256 hash pinning #232

Closed
opened 2026-07-30 01:43:59 +02:00 by fable-5 · 1 comment
Collaborator

Plan reference: 20-massnahmenplan.md -> Phase 4
ADR: ADR 0025
Effort: L (8–10 AT)
Depends on: #200

Context

Hash pinning is the right answer to plugin trust; it is not the most urgent
one, because #200's hard off-switch already closes the risk for the offer
stage. Real code signing is unavailable without a legal entity to hold a
signing identity (ADR 0025).

Current state

  • Plugins declare a manifest.json
    (e.g. packages/plugins/drawio/manifest.json: id, version,
    apiVersion, kind, extensionPoints, permissions, fallback) —
    there is no hash or signature field.
  • Bundles are shipped as zip artefacts
    (packages/plugins/drawio/dist/drawio-1.0.0.zip); loading is gated by
    the sandbox (ADR 0008) and per-pond enablement, not by identity.
  • instance_settings is the place for the allowlist
    (apps/api/prisma/schema.prisma:17–23).

Acceptance criteria

  • The manifest carries a SHA-256 over the bundle; the hash is verified
    on install and on every load, failing closed with a clear error.
  • An allowlist in instance_settings names permitted plugin ids with
    their pinned hashes; a plugin outside it does not load even if
    installed.
  • Admin UI to review the allowlist and the hash actually seen versus
    the one pinned.
  • Every rejection is audited (catalogue event per #201).
  • Tests: tampered bundle rejected; unpinned plugin rejected;
    version bump requires an explicit re-pin.
  • docs/architecture/plugin-architecture.md and #227 document the
    model.

Out of scope

Code signing with a certificate, a plugin marketplace, and network
allowlisting for plugins (deliberately unscheduled).


Vier Befunde, die 10-ist-aufnahme.md zusätzlich zum Plan gefunden hat.
Drei betreffen unbefristete Inhaltskopien, einer die Reproduzierbarkeit.

**Plan reference:** `20-massnahmenplan.md` -> Phase 4 **ADR:** ADR 0025 **Effort:** L (8–10 AT) **Depends on:** #200 ## Context Hash pinning is the right answer to plugin trust; it is not the most urgent one, because #200's hard off-switch already closes the risk for the offer stage. Real code signing is unavailable without a legal entity to hold a signing identity (ADR 0025). ## Current state - Plugins declare a `manifest.json` (e.g. `packages/plugins/drawio/manifest.json`: `id`, `version`, `apiVersion`, `kind`, `extensionPoints`, `permissions`, `fallback`) — there is no hash or signature field. - Bundles are shipped as zip artefacts (`packages/plugins/drawio/dist/drawio-1.0.0.zip`); loading is gated by the sandbox (ADR 0008) and per-pond enablement, not by identity. - `instance_settings` is the place for the allowlist (`apps/api/prisma/schema.prisma:17–23`). ## Acceptance criteria - [ ] The manifest carries a SHA-256 over the bundle; the hash is verified on install **and** on every load, failing closed with a clear error. - [ ] An allowlist in `instance_settings` names permitted plugin ids with their pinned hashes; a plugin outside it does not load even if installed. - [ ] Admin UI to review the allowlist and the hash actually seen versus the one pinned. - [ ] Every rejection is audited (catalogue event per #201). - [ ] Tests: tampered bundle rejected; unpinned plugin rejected; version bump requires an explicit re-pin. - [ ] `docs/architecture/plugin-architecture.md` and #227 document the model. ## Out of scope Code signing with a certificate, a plugin marketplace, and network allowlisting for plugins (deliberately unscheduled). --- Vier Befunde, die `10-ist-aufnahme.md` zusätzlich zum Plan gefunden hat. Drei betreffen unbefristete Inhaltskopien, einer die Reproduzierbarkeit.
fable-5 added this to the M31 — VS-NfD: backlog milestone 2026-07-30 01:43:59 +02:00
fable-5 added the
area:supply-chain
effort:L
vs-nfd
labels 2026-07-30 01:43:59 +02:00
fable-5 referenced this issue from a commit 2026-07-31 10:01:14 +02:00
fable-5 referenced this issue from a commit 2026-07-31 10:35:39 +02:00
Author
Collaborator

Done via PR #298 (merged, CI run 646 green, CD 645 deployed Test+Int, readyz fully green on both). M31 complete — with it, every planned VS-NfD milestone (M24-M32) is done.

All acceptance criteria met:

  • SHA-256 over the delivered bundle recorded at install (plugins.bundle_hash); verified on install AND on every load, failing closed with stable codes (plugin_not_pinned / plugin_hash_mismatch).
  • plugins.allowlist in instance_settings: empty = not enforced (backward compatible); non-empty = a plugin outside it does not load even if installed (absent from mount lists, frame/assets 404).
  • Admin UI shows observed vs pinned hash per plugin with pin / re-pin / unpin.
  • Every rejection audited: plugin.rejected, audit catalogue v1.5.
  • Tests: tampered bundle rejected; unpinned plugin rejected; version bump requires explicit re-pin; pin drift blocks loading while the admin still sees the mismatch; empty-allowlist compatibility. Full api suite 101 files / 561 green.
  • Documented in plugin-architecture.md (trust section, scope stated honestly per ADR 0019) and the hardening guide; residual risk R-03 resolved.

Out of scope stayed out: no code signing (no signing identity, ADR 0025), no marketplace, no network allowlisting.

Done via PR #298 (merged, CI run 646 green, CD 645 deployed Test+Int, readyz fully green on both). **M31 complete — with it, every planned VS-NfD milestone (M24-M32) is done.** All acceptance criteria met: - SHA-256 over the delivered bundle recorded at install (`plugins.bundle_hash`); verified on install AND on every load, failing closed with stable codes (`plugin_not_pinned` / `plugin_hash_mismatch`). - `plugins.allowlist` in `instance_settings`: empty = not enforced (backward compatible); non-empty = a plugin outside it does not load even if installed (absent from mount lists, frame/assets 404). - Admin UI shows observed vs pinned hash per plugin with pin / re-pin / unpin. - Every rejection audited: `plugin.rejected`, audit catalogue v1.5. - Tests: tampered bundle rejected; unpinned plugin rejected; version bump requires explicit re-pin; pin drift blocks loading while the admin still sees the mismatch; empty-allowlist compatibility. Full api suite 101 files / 561 green. - Documented in `plugin-architecture.md` (trust section, scope stated honestly per ADR 0019) and the hardening guide; residual risk R-03 resolved. Out of scope stayed out: no code signing (no signing identity, ADR 0025), no marketplace, no network allowlisting.
Sign in to join this conversation.
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: stwaidele/dorfteich#232
No description provided.