Skip to content

fix(security): harden self-update with tagged refs + SHA-256 verification [DEVA11Y-478] - #27

Open
sunny-se wants to merge 1 commit into
mainfrom
fix/DEVA11Y-478-secure-self-update
Open

fix(security): harden self-update with tagged refs + SHA-256 verification [DEVA11Y-478]#27
sunny-se wants to merge 1 commit into
mainfrom
fix/DEVA11Y-478-secure-self-update

Conversation

@sunny-se

@sunny-se sunny-se commented Jun 9, 2026

Copy link
Copy Markdown
Collaborator

Summary

How it works

  1. Script has embedded SCRIPT_VERSION="v1.0.0"
  2. On startup, fetches lightweight scripts/latest-version.txt from main (metadata only, not executable)
  3. If remote version differs: fetches script + SHA256SUMS from the immutable tagged ref
  4. Verifies SHA-256 checksum of downloaded script against SHA256SUMS
  5. Only overwrites if checksum matches — warns and aborts on mismatch

Migration (backwards compat)

Old scripts on dev machines still have the old self-update pointing at refs/heads/main. When this merges, they'll self-update from main one last time (final insecure fetch), pulling the new secure mechanism. All subsequent updates go through the verified tagged path.

Post-merge action required

Immediately after merge, create and push the v1.0.0 tag:

git tag v1.0.0 <merge-commit-sha>
git push origin v1.0.0

Files changed

File Change
scripts/{bash,zsh,fish}/{spm,cli}.sh (6 files) Add SCRIPT_VERSION, replace script_self_update()
scripts/latest-version.txt New — version pointer (fetched from main)
scripts/SHA256SUMS New — checksums for all 6 scripts (fetched from tag)

Test plan

  • grep -r "refs/heads/main" scripts/ --include="*.sh" — no mutable refs in download URLs
  • SCRIPT_VERSION present in all 6 scripts
  • shasum -a 256 verification in all 6 scripts
  • cd scripts && shasum -a 256 -c SHA256SUMS — all 6 OK

Jira

DEVA11Y-478

🤖 Generated with Claude Code

…tion (DEVA11Y-478)

Self-update previously fetched executable code from refs/heads/main with
only a shebang check (CWE-494, CVSS 7.8). Now:

1. Version pointer (latest-version.txt) fetched from main — metadata only
2. Actual script fetched from immutable tagged ref (refs/tags/vX.Y.Z)
3. SHA-256 checksum verified against SHA256SUMS before overwriting

Migration: old scripts on dev machines will self-update from main one
last time, pulling the new mechanism. All subsequent updates go through
the verified tagged path.

Post-merge: tag the merge commit as v1.0.0 and push tag immediately.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@sunny-se
sunny-se requested a review from a team as a code owner June 9, 2026 06:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant