Skip to content

Harden the release path and add community docs - #208

Open
detkin wants to merge 1 commit into
mainfrom
harden-release-path
Open

Harden the release path and add community docs#208
detkin wants to merge 1 commit into
mainfrom
harden-release-path

Conversation

@detkin

@detkin detkin commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Summary

Follow-up from an open-source readiness audit of this repo. Everything here is either a concrete defect or a gap relative to what a public repo with this much traffic should have.

1. install.sh never verified its download

This is the one I'd merge first. The documented install path is a script piped straight into a shell, and it downloaded the release archive, extracted it, and installed the binary to ~/.local/bin without checking anything. A corrupted mirror, a truncated transfer, or a tampered artifact installed silently.

It now fetches the release's checksums.txt, hashes the archive with whichever of sha256sum / shasum the platform provides, and refuses to install on a mismatch — or when the checksums can't be fetched at all, rather than falling back to trusting the download.

2. Build provenance attestation

release.yml now mints a signed provenance statement for the published archives via actions/attest-build-provenance, so users can tie an artifact to this repository and commit:

gh attestation verify sx_Darwin_arm64.tar.gz --repo sleuth-io/sx

Checksums prove the archive matches a hash file published alongside it; attestation proves it came from this build. The job gains id-token: write and attestations: write for this.

3. The Homebrew formula declared the wrong license

.goreleaser.yml had license: MIT. The repository is Apache-2.0. Every formula published through v2.2.8 has told brew info sx the wrong license. One-line fix; takes effect on the next release.

4. Dependabot didn't cover Go modules

dependabot.yml configured github-actions only, so Go dependencies never received update PRs — they'd only ever surface as security alerts after a CVE landed. Added gomod, weekly, grouped for minor/patch.

5. claude-pr-review.yml had no fork guard

Every fork PR triggered the review with empty secrets. Added the guard job pattern: fork PRs and repos without ANTHROPIC_API_KEY skip cleanly, and a missing SKILLS_SITE_API_KEY degrades to a review without installed skills instead of failing.

6. Community docs

Added SECURITY.md, CONTRIBUTING.md, CODE_OF_CONDUCT.md, issue templates, and a PR template — none existed. SECURITY.md points at GitHub private vulnerability reporting (now enabled), so there's a private channel for reports.

Testing

  • make prepush — green, all 44 packages pass.
  • bash -n install.sh — syntax clean.
  • Installer verified against the real v2.2.8 release: downloaded the actual archive and checksums.txt, confirmed the grep/awk extraction matches goreleaser's format, and ran the full script end to end — installs and reports ✓ Checksum verified, then sx --version works.
  • Failure path verified: appended a byte to the archive after download; the script reported the mismatch, refused to install, and left nothing in the install dir.
  • All changed YAML parses.

Notes

Applied alongside this, via the API rather than in the diff:

Setting Before Now
Secret scanning disabled enabled
Push protection disabled enabled
Dependabot security updates disabled enabled
Private vulnerability reporting disabled enabled
Default workflow token write read
Token can approve PRs yes no
Branch protection on main none PR + Test required
Topics none 12
Homepage unset https://sleuth-io.github.io/sx/

Dropping the default workflow token to read is safe: release.yml, app-release.yml, pages.yml, and claude-pr-review.yml each declare their own permissions: block, and test.yml needs nothing beyond read. Worth watching the next release run to confirm.

SECURITY.md references attestation as available "from v2.2.9 onward" — accurate if this merges before the next tag, worth a tweak if it doesn't.

install.sh piped into a shell was extracting and installing an archive
it never verified. It now downloads the release's checksums.txt, hashes
the archive with whichever of sha256sum/shasum the platform has, and
refuses to install on a mismatch or when the checksums cannot be
fetched.

The release workflow also mints a signed build provenance attestation
for the published archives, so `gh attestation verify` can tie an
artifact to this repo and commit rather than to a hash file published
next to it.

Other fixes:

- The Homebrew formula declared license: MIT while the repository is
  Apache-2.0. Every published formula has carried the wrong license.
- dependabot.yml covered github-actions but not gomod, so Go
  dependencies never got update PRs. Added, grouped weekly.
- claude-pr-review.yml had no fork or missing-secret guard, so every
  fork PR ran it with empty secrets. Added the guard job; forks and
  unconfigured repos now skip cleanly, and a missing skills key
  degrades to a review without skills.
- Added SECURITY.md (pointing at private vulnerability reporting),
  CONTRIBUTING.md, CODE_OF_CONDUCT.md, issue templates, and a PR
  template.

Verified the installer against the real v2.2.8 artifacts: a clean
install succeeds and verifies, and a tampered archive is rejected with
nothing installed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01McaR57BWnn1YqFGo3NdxES
@detkin
detkin requested review from inesp, mrdon and mzgajner as code owners July 29, 2026 00:10
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