From 517503cb291846f0ec53d39359efb3bea182e1d7 Mon Sep 17 00:00:00 2001 From: Levi Durfee Date: Fri, 16 Oct 2026 00:55:36 +0000 Subject: [PATCH] Ship an SBOM with each binary and check for vulnerabilities GoReleaser now makes a CycloneDX SBOM for each binary with Syft, from the binary's build information, named like the binary and listed in SHA256SUMS. CI installs Syft, so the snapshot build checks this on every pull request. A govulncheck job fails CI when the code calls a function with a known vulnerability. Its first run found eight standard-library vulnerabilities in what Go 1.27.0 builds, which v0.1.0 and v0.1.1 were built with; Go 1.27.2 fixes them. CI and releases now build with the newest Go release, and go.mod asks for at least 1.27.2, so that "go install" users get the fixes too. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01NTEjHbdKp83qgQgmqR1BJ6 --- .github/workflows/ci.yml | 22 ++++++++++++++++++++-- .github/workflows/release.yml | 8 +++++++- .goreleaser.yaml | 11 +++++++++++ docs/releasing.md | 7 +++++++ go.mod | 2 +- 5 files changed, 46 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 043df80..f97242a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,9 +15,11 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false + # The newest Go release, so that binaries get its security fixes. - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: - go-version-file: go.mod + go-version: stable + check-latest: true - run: make vet test race # Builds every release target with the release config, without signing. @@ -27,10 +29,26 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false + # The newest Go release, so that binaries get its security fixes. - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: - go-version-file: go.mod + go-version: stable + check-latest: true + # GoReleaser makes each binary's SBOM with Syft. + - uses: anchore/sbom-action/download-syft@66cbf4bc1f1c0d2edc94016e65bc221b6bb0ad6c # v0.24.3 + with: + syft-version: v1.54.1 - uses: goreleaser/goreleaser-action@f06c13b6b1a9625abc9e6e439d9c05a8f2190e94 # v7.2.3 with: version: v2.18.3 args: release --snapshot --clean + + # Fails when the code calls a function with a known vulnerability, in a + # module or in the Go standard library. + vulncheck: + runs-on: ubuntu-latest + steps: + - uses: golang/govulncheck-action@032d45514ae346b1db93c04b0c90b841c370344f # v1.1.0 + with: + go-version-input: stable + check-latest: true diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 91c8204..e8f52b6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -54,12 +54,18 @@ jobs: with: fetch-depth: 0 # the changelog needs the previous tag persist-credentials: false + # The newest Go release, so that binaries get its security fixes. - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: - go-version-file: go.mod + go-version: stable + check-latest: true cache: false # build release binaries from a clean module cache - run: make vet test race + # GoReleaser makes each binary's SBOM with Syft. + - uses: anchore/sbom-action/download-syft@66cbf4bc1f1c0d2edc94016e65bc221b6bb0ad6c # v0.24.3 + with: + syft-version: v1.54.1 - uses: goreleaser/goreleaser-action@f06c13b6b1a9625abc9e6e439d9c05a8f2190e94 # v7.2.3 with: version: v2.18.3 diff --git a/.goreleaser.yaml b/.goreleaser.yaml index db4a763..6e6aaa8 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -24,6 +24,17 @@ archives: - formats: [binary] name_template: "{{ .ProjectName }}-{{ .Os }}-{{ .Arch }}" +# A CycloneDX SBOM for each binary, named like it: rypt-linux-amd64.cdx.json +# and so on. Syft reads the Go version and the modules from the binary's +# build information, so the SBOM lists exactly what was compiled in. +sboms: + - id: binaries + artifacts: binary + cmd: syft + args: ["$artifact", "--output", "cyclonedx-json=$document", "--quiet"] + documents: + - "{{ .ProjectName }}-{{ .Os }}-{{ .Arch }}.cdx.json" + checksum: name_template: SHA256SUMS algorithm: sha256 diff --git a/docs/releasing.md b/docs/releasing.md index 8fe4523..72d6130 100644 --- a/docs/releasing.md +++ b/docs/releasing.md @@ -20,6 +20,13 @@ The release binaries are named and checksummed the same way as `make dist` output: `rypt-linux-amd64`, `rypt-darwin-arm64`, `rypt-windows-amd64.exe`, and so on. +Each binary has a CycloneDX SBOM beside it, named like it +(`rypt-linux-amd64.cdx.json`), which GoReleaser makes with Syft from the +binary's own build information: the Go version and every module compiled in. +The SBOMs are listed in `SHA256SUMS` too. The release workflow builds with +the newest Go release, whatever go.mod's `go` line says, so that binaries +get the standard library's security fixes. + [.github/workflows/ci.yml](../.github/workflows/ci.yml) runs the same tests on every push to `main` and every pull request, and builds all six targets with the release configuration, unsigned. diff --git a/go.mod b/go.mod index a5172f8..4b89f14 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/x6c-co/rypt-cli -go 1.27.0 +go 1.27.2 require ( github.com/x6c-co/rypt v0.1.0