Skip to content

fix(install): add SHA-256 verification for cli.js download#3389

Open
la14-1 wants to merge 1 commit intomainfrom
fix/install-sha256
Open

fix(install): add SHA-256 verification for cli.js download#3389
la14-1 wants to merge 1 commit intomainfrom
fix/install-sha256

Conversation

@la14-1
Copy link
Copy Markdown
Member

@la14-1 la14-1 commented May 3, 2026

Why: Prevents MITM/tampered binary downloads by verifying SHA-256 of cli.js before execution — closes the last unverified download in the install path (bun installer already has hash verification).

Changes

  • Downloads cli.js.sha256 companion file from the same GitHub Release
  • Verifies the hash using the existing portable sha256_file() helper (works on both macOS shasum and Linux sha256sum)
  • On hash mismatch: aborts with a clear error (same UX as the bun installer hash check)
  • On missing checksum file (not yet published by CI): warns and continues — zero breakage for existing installs
  • On missing hash tools: warns and continues (same graceful degradation as bun check)

Remaining work (separate PR, requires human review)

.github/workflows/release.yml must be updated to publish cli.js.sha256 alongside cli.js in the cli-latest release. Workflow changes are off-limits for automated PRs per team rules. Once CI publishes the checksum file, this verification activates automatically.

Fixes #3327

The install script downloads cli.js from GitHub Releases but does not
verify its integrity, unlike the bun installer which checks a pinned
SHA-256 hash. This adds checksum verification using a companion
cli.js.sha256 release artifact (same pattern as the bun hash check).

When the checksum file is not yet published, the installer warns and
continues — once CI publishes cli.js.sha256, verification activates
automatically with no further install.sh changes needed.

Fixes #3327

Agent: security-auditor
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Copy link
Copy Markdown
Member Author

@la14-1 la14-1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security Review: PR #3389 — SHA-256 verification for cli.js download

Does the fix address the vulnerability in #3327?

Partially. This PR adds the client-side verification logic to install.sh, which is the necessary first half. However, as #3327 explicitly notes, both halves are needed:

  1. install.sh side (this PR): Download cli.js.sha256, verify the hash of cli.js before installing. Done correctly.
  2. CI side (not in this PR): Publish cli.js.sha256 alongside cli.js in the cli-latest release. Without this, the verification is a no-op — the script gracefully degrades with "No cli.js.sha256 checksum published yet — skipping verification".

Findings

Positive:

  • The sha256_file helper already exists on main (portable macOS/Linux implementation). The PR reuses it correctly.
  • The tr -d '[:space:]' on the expected hash is a good defensive measure against trailing newlines in the checksum file.
  • Graceful degradation is implemented at two levels: (a) no checksum file published yet, (b) no sha256sum/shasum binary available. Both log warnings instead of failing.
  • The error messaging on mismatch is excellent — clear "possible supply chain attack" language with the expected vs actual hashes and a pointer to the issues page.
  • The --proto '=https' flag on the checksum download enforces HTTPS, preventing downgrade attacks.
  • The curl for the checksum file uses 2>/dev/null to suppress errors when the file doesn't exist yet, which is appropriate.

Concerns:

  1. TOCTOU is not a risk here — the downloaded cli.js is verified in the same tmpdir before being copied to the install location. No race window.
  2. The checksum file format is simple — just the hex digest, no filename. This matches the implementation (tr -d '[:space:]' strips any whitespace). Consistent with common practice.
  3. Until CI publishes the .sha256 file, this provides zero protection. The graceful skip means an attacker who compromises only the cli.js artifact (but not .sha256 because it doesn't exist) gets through silently. This is acceptable as a phased rollout — the warning makes it visible that verification is not happening.

Recommendation: This PR is correct and safe to merge. The CI-side companion change (publishing cli.js.sha256 in the release workflow) should be tracked as a follow-up — without it, the verification is dormant. Is there an issue tracking the CI side?

-- refactor/security-auditor

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.

security: cli.js download in install.sh has no SHA-256 verification (unlike bun installer)

2 participants