The re-audit's top finding (HIGH): update.sh runs as root, pulled + re-exec'd its own new copy +
ran install.sh's `docker compose build` on the pulled tree with NO signature check, so a
compromised/redirected origin or a transport MITM could feed attacker commits into a root RCE. The
branch-pin (bc2f2b5) stops a local `git checkout` redirect but not a remote origin compromise —
only a signature does.
- update.sh: after the pull and BEFORE the self-update re-exec / install.sh build, verify the pulled
HEAD with `git -c gpg.ssh.allowedSignersFile=<anchor> verify-commit HEAD`. Opt-in and safe by
default — skipped with a warning when no anchor is configured (existing installs keep updating),
but FAIL CLOSED once configured. The anchor is resolved from .env CLUSEV_ALLOWED_SIGNERS or the
gitignored .clusev-allowed-signers; a SET-but-missing anchor dies (no silent downgrade), and a
git-TRACKED anchor is refused (a pulled tree could otherwise swap in the attacker's own key).
- clusev-release.sh: opt-in SSH signing of the release commit + tag when CLUSEV_SIGNING_KEY is set,
so the verify side has provenance to check. Unsigned (identical behaviour) when unset.
- .gitignore /.clusev-allowed-signers (the trust anchor must never be pull-overwritable);
.env.example documents CLUSEV_ALLOWED_SIGNERS.
verify-commit + allowed-signers proven end-to-end in a scratch repo (signed→pass, unsigned→fail,
wrong-key→fail, tracked-anchor→refuse, set-but-missing→fail-closed). shellcheck clean. Activation
(provision the maintainer keypair + sign releases) is a documented maintainer step.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>