Skip to content

ci: supply chain hardening and releases with slsa provenance - #4

Merged
t0d0r merged 6 commits into
masterfrom
ci/supply-chain-release
Nov 2, 2026
Merged

t0d0r merged 6 commits into
masterfrom
ci/supply-chain-release

Conversation

@t0d0r

@t0d0r t0d0r commented Nov 2, 2026

Copy link
Copy Markdown
Owner

What

Supply chain hardening and releases built in CI with signed SLSA
provenance. Five commits, one concern each:

  1. ci: pin every action, add CodeQL and Dependabot. Every uses: is a
    full commit SHA with the version in a comment. golangci-lint-action
    goes v8 -> v9.3.0: v8 ignored install-only, so the linter ran
    twice. golangci-lint is pinned to v2.15.0. CodeQL runs on PRs, master
    and weekly. Dependabot runs weekly, grouped, with a 7-day cooldown and
    Conventional Commit prefixes.

  2. build(deps): golang.org/x/net 0.62.0 (GO-2026-6860, GO-2026-6866).
    osv-scanner.toml skips GO-2026-5932 (x/crypto/openpgp, no fixed
    version, never imported) until 2027-05-01.

  3. docs: SECURITY.md. Private reporting through GitHub, which is now
    enabled on the repository. 7 / 14 / 90 day expectations, scope, and
    how to verify a release.

  4. ci(release): the Release workflow. A pushed vX.Y.Z tag on
    master:

    • build job, read-only token: tag and master checks,
      make test, make dist.
    • publish job, no repository code: checks SHA256SUMS,
      actions/attest (SLSA build provenance over every file),
      attaches lazygram-vX.Y.Z.intoto.jsonl, gh release create.

    make release now refuses, so no release goes out without
    provenance.

  5. docs: specs, README, packaging notes, todo, session note.

Why GitHub artifact attestations, not slsa-github-generator

The generator has been unmaintained since August 2026; its README says
so and points to artifact attestations. It also cannot be pinned to a
commit. actions/attest is GitHub's own and is pinned like every other
action.

Reviewed before opening

An independent review confirmed 15 findings, all fixed here. The main
ones:

  • The documented verify command now pins the workflow and the tag:
    --signer-workflow t0d0r/lazygram/.github/workflows/release.yml --source-ref refs/tags/vX.Y.Z --deny-self-hosted-runners.
    --repo alone accepts any workflow of the repo from any branch.
  • No publishing fallback without provenance.
  • golangci-lint pinned.
  • CodeQL's contents: read made explicit.
  • No pacman -Syu promise before the Omarchy package exists.

Expected Scorecard effect

The next run after merge should show these changes:

  • Pinned-Dependencies 3 -> 10
  • SAST 0 -> 7
  • Security-Policy 0 -> 10
  • Dependency-Update-Tool 0 -> 10
  • Vulnerabilities 7 -> 10
  • Branch-Protection 0 -> 3 (the master ruleset is already active)

Fuzzing 0 -> 10 comes with the fuzzing PR. Signed-Releases 0 -> 10 comes
with v0.4.22, once the older releases are deleted. Overall about 3.7 ->
7+.

Not in this PR (repository settings, your call)

  • Dependabot alerts and security updates (both off now).
  • Immutable releases.
  • A ruleset for v* tags.
  • Pull requests required on master.

After merge

Tag v0.4.22 on master and push the tag. Then:

  1. Verify per specs/release.md, Publishing, step 4.
  2. Update Homebrew, the PKGBUILD and Add lazygram 0.4.30: terminal Telegram client (TUI) omacom/omarchy-pkgs#2022.
  3. Delete the releases v0.3.0..v0.4.21 (tags stay).

Checks

make check and actionlint are clean. govulncheck: no reachable
vulnerability. It merges cleanly with #3.

t0d0r added 5 commits November 2, 2026 21:37
Linux and macOS: checkout v7.0.1, setup-go v7.0.0 and
golangci-lint-action v9.3.0, each by full commit SHA with the version
in a comment, checkout without persisted credentials. v9 knows the
install-only input that v8 ignored, so the action no longer runs the
linter a second time; golangci-lint itself is pinned to v2.15.0.

CodeQL analyses the Go code on pull requests, pushes to master and
weekly, with contents: read and security-events: write only.

Dependabot proposes Go module and action updates weekly, one grouped
pull request per ecosystem, after a 7-day cooldown, with build(deps)
and ci(deps) commit prefixes.
golang.org/x/net 0.62.0 fixes GO-2026-6860 and GO-2026-6866 (html);
lazygram does not call them, but they counted against Scorecard's
Vulnerabilities check.

osv-scanner.toml skips GO-2026-5932 until 2027-05-01: the unmaintained
golang.org/x/crypto/openpgp package has no fixed version, and
govulncheck shows lazygram never imports it.
Reports go privately through GitHub's private vulnerability reporting.
The policy states response times (7 days to acknowledge, 14 to assess,
90 to a fixed release), disclosure through a GitHub security advisory,
the supported version (the latest release), the scope, and how to
verify a release's provenance with gh attestation verify pinned to the
Release workflow and the tag.
A pushed vX.Y.Z tag on master runs the Release workflow. The build job
has a read-only token: it refuses a malformed tag or a commit not on
master, runs make test and make dist with an empty module cache, and
hands dist/ on as an artifact. The publish job runs no repository code:
it checks SHA256SUMS, creates one SLSA build provenance attestation for
every listed file with actions/attest, attaches it as
lazygram-vX.Y.Z.intoto.jsonl and creates the release.

make release no longer publishes from a workstation; it points at the
workflow, so every release from v0.4.22 on carries provenance.
specs/ci.md covers pinned actions, CodeQL, Dependabot and the Release
workflow; specs/release.md the new publishing procedure, verification
and the decisions (artifact attestations over the unmaintained
slsa-github-generator, separate build and publish jobs, deleting the
releases up to v0.4.21 once v0.4.22 is verified); specs/security.md
the vulnerability policy, ignored advisories and provenance. README
shows the verify command. The packaging notes record the deleted stray
tag. todo gains a supply chain section and a session note records the
work and the open repository settings.
@github-advanced-security

Copy link
Copy Markdown

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

The Linux and macOS jobs were both named "check", which made a required
status check ambiguous; they are now "Linux" and "macOS", and only
Linux is required, because macOS runners are sometimes unavailable.

specs/ci.md gains a Repository settings section: the master ruleset
(pull request and a passing Linux check on an up-to-date branch, no
deletion or force push, no bypass), the release tags ruleset for v*,
immutable releases, private vulnerability reporting and Dependabot
alerts and security updates. specs/release.md states what immutable
releases protect and what they do not.
@t0d0r
t0d0r merged commit bb59782 into master Nov 2, 2026
4 checks passed
@t0d0r
t0d0r deleted the ci/supply-chain-release branch November 2, 2026 22:17
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.

2 participants