Skip to content

fix(hooks): pin the cbm installer's sha256 instead of fetching it - #136

Merged
github-actions[bot] merged 1 commit into
mainfrom
claude/cbm-pin-sha256-opdwue
Aug 1, 2026
Merged

fix(hooks): pin the cbm installer's sha256 instead of fetching it#136
github-actions[bot] merged 1 commit into
mainfrom
claude/cbm-pin-sha256-opdwue

Conversation

@dizhaky

@dizhaky dizhaky commented Aug 1, 2026

Copy link
Copy Markdown
Owner

What does this PR do?

Follow-up to #135. Closes a supply-chain gap in the installer that PR added. Mirrors crm-pipeline #266, which has the byte-identical file — verified before writing this.

.claude/hooks/session-start.sh verified the downloaded codebase-memory-mcp tarball against a checksums.txt fetched from the same GitHub release as the tarball:

curl -fsSL -o "$tmp/$asset"         "$base/$asset"
curl -fsSL -o "$tmp/checksums.txt"  "$base/checksums.txt"   # same origin
grep " ${asset}\$" checksums.txt | sha256sum -c -

That proves the download wasn't corrupted in transit. It proves nothing about the publisher — anyone who can alter the release alters both files together, and verification still passes.

It matters more than usual here: cbm-code-discovery-gate runs the binary on every PreToolUse once the hook is registered. A swapped artifact would execute constantly, not once.

Related Issue

Follow-up to #135 (same investigation that produced #134).

Type of Change

  • 🔒 Security fix

Changes Made

Per-arch sha256 values pinned in the script. A hash committed in the repo is an independent reference — it fails closed if the tag is ever re-pointed or the asset re-uploaded.

CBM_SHA256_amd64="e2832a8d207c26beaa30efa6222ed4a37cb3f526ca4bee060bfbf336ed6fc679"
CBM_SHA256_arm64="68a345d9a6842f02a3cb07e187b28bc38c4f3a22967f47fadbcd0757ba93a680"

An arch with no pin is now a hard stop, not a fall-through to an unverified install.

This is the pattern this repo's own gitleaks workflow already uses (#116: pinned by version and tarball sha256), so it's consistency rather than novelty.

Provenance of the pinned values

Both linux tarballs were downloaded and sha256sum'd locally; the computed digests matched the release's checksums.txt for linux-amd64 and linux-arm64. The pinned values are the computed ones, not transcribed — otherwise this would just relocate the same unverified trust from runtime into the repo.

How to Test

bash -n .claude/hooks/session-start.sh

# no-op off-remote
bash .claude/hooks/session-start.sh; echo $?            # 0, silent

# happy path in a throwaway HOME
T=$(mktemp -d); CLAUDE_CODE_REMOTE=true HOME=$T CLAUDE_PROJECT_DIR=$PWD \
  bash .claude/hooks/session-start.sh
ls $T/.local/bin $T/.claude/hooks

# negative: corrupt the pin, confirm it refuses
sed 's/^CBM_SHA256_amd64=.*/CBM_SHA256_amd64="0000...0000"/' \
  .claude/hooks/session-start.sh > /tmp/bad.sh
T2=$(mktemp -d); CLAUDE_CODE_REMOTE=true HOME=$T2 CLAUDE_PROJECT_DIR=$PWD bash /tmp/bad.sh
[ -e "$T2/.local/bin/codebase-memory-mcp" ] && echo FAIL || echo "correctly refused"

Verification

Run against the identical crm-pipeline file — bash -n clean, plus four cases against a fresh HOME:

# Case Result
1 not remote silent no-op, exit 0
2 remote, happy path downloads, verifies, installs binary + both hooks, reports codebase-memory-mcp 0.9.0
3 deliberately corrupted pin refuses to install, prints expected vs actual, exit 0
4 unknown arch refuses

Case 3 is the one that matters — a verifier that never fails closed is decoration.

No Python touched.

Follow-up not in this PR

The /Users/danizhaky/.local/bin symlink remains a workaround for a Mac-absolute path hardcoded in .claude/settings.json and the cbm-* hooks. Un-hardcoding that path is the real fix; the symlink is debt.


Generated by Claude Code

The installer verified the downloaded codebase-memory-mcp tarball against a
checksums.txt fetched from the same GitHub release as the tarball. That proves
the download wasn't corrupted in transit; it proves nothing about the
publisher. Anyone able to alter the release alters both files together and
verification still passes.

Replaced with per-arch sha256 values pinned in the script. A hash committed
here is an independent reference: it fails closed if the tag is ever
re-pointed or the asset re-uploaded.

This matters more than usual because cbm-code-discovery-gate executes the
binary on every PreToolUse once the hook is registered — a swapped artifact
would run constantly, not once. It is also the pattern this repo's own
gitleaks workflow already uses (pinned by version AND tarball sha256), so this
is consistency rather than novelty.

An arch with no pinned hash is now a hard stop rather than a fall-through to
an unverified install.

Provenance: both linux tarballs were downloaded and sha256sum'd locally, and
the computed digests matched the release's checksums.txt. The pinned values
are the computed ones, not transcribed.

Mirrors crm-pipeline NousResearch#266.
@dizhaky
dizhaky marked this pull request as ready for review August 1, 2026 21:27
@github-actions
github-actions Bot merged commit 35452fb into main Aug 1, 2026
23 checks passed
@github-actions
github-actions Bot deleted the claude/cbm-pin-sha256-opdwue branch August 1, 2026 21:27
@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown

🔎 Lint report: claude/cbm-pin-sha256-opdwue vs origin/main

ruff

Total: 0 on HEAD, 0 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 9238 on HEAD, 9238 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 5103 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant