Hardening Go Supply Chains With SLSA Level 3 Builds

Cybersecurity
Date:November 13, 2026
Topic:
Hardening Go Supply Chains With SLSA Level 3 Builds
⏱ 2 min read

Your Go binary runs in production. But can you prove it was built from the exact source you reviewed, on infrastructure you trust, without a single artifact swapped along the way? Most teams cannot. SLSA Level 3 changes that.

Why SLSA Level 3 Matters for Go

SLSA (Supply-chain Levels for Software Artifacts) Level 3 requires hardened builds, non-falsifiable provenance, and isolation between build steps. For Go projects, this means reproducible builds where go build yields identical binaries every time, provenance attestations signed by the build platform (not your CI keys), and verification gates before deployment.

The Go Reproducibility Baseline

Go 1.21+ enables reproducible builds by default when you control the module cache and build environment. Pin the toolchain, disable CGO, and fix timestamps.

bash
# .github/workflows/slsa.yml
env:
  GOFLAGS: "-trimpath -buildvcs=false"
  CGO_ENABLED: "0"
  SOURCE_DATE_EPOCH: "1704067200" # fixed timestamp

steps:
  - uses: actions/setup-go@v5
    with:
      go-version: '1.22.5'  # pin exact version
      cache: true
  - run: go mod download
  - run: go build -ldflags="-s -w" -o myapp .
💡
TipUse -trimpath to strip local filesystem paths from the binary. Set SOURCE_DATE_EPOCH to a fixed value (e.g., release tag date) for bit-for-bit reproducibility.

Generating SLSA Provenance with GitHub Actions

The slsa-framework/slsa-github-generator action produces in-toto attestations signed by GitHub's OIDC identity, not a long-lived key you manage.

yaml
- uses: slsa-framework/slsa-github-generator/generic@v1.9.0
  with:
    base64-subjects: "${{ hashFiles('myapp') }}"
    provenance-name: "myapp.intoto.jsonl"
    upload-assets: true

This emits myapp.intoto.jsonl containing the build definition, materials (Go modules, source commit), and a Sigstore bundle. The signature chains to GitHub's OIDC issuer, verifiable without secrets.

Verifying at Deploy Time

Policy engines like cosign and kyverno enforce provenance before admission.

bash
# Verify provenance matches expected source
cosign verify-attestation \
  --type slsaprovenance \
  --policy policy.rego \
  ghcr.io/yourorg/myapp:v1.2.3
rego
package verify

default allow = false

allow {
  input.predicate.buildType == "https://github.com/slsa-framework/slsa-github-generic@v1"
  input.predicate.invocation.configSource.uri == "github.com/yourorg/myapp"
  input.predicate.invocation.configSource.digest == "sha256:<expected-commit-sha>"
  input.predicate.materials[_].uri == "github.com/yourorg/myapp"
}
⚠️
WarningPin the generator version (v1.9.0 above). Floating tags break reproducibility and invalidate your provenance chain.

Go Module Transparency with OSS Rebuild

Google's OSS Rebuild independently reproduces Go modules from source and publishes SLSA Level 3 provenance to the go.transparency.dev log. Your CI can cross-reference this log to detect compromised upstream modules before they enter your build.

bash
# Check if module exists in transparency log
curl -s "https://go.transparency.dev/api/v1/entries?module=github.com/example/[email protected]" | jq

Putting It All Together

1. Pin Go toolchain and enable reproducible flags in every workflow. 2. Run slsa-github-generator on every release tag. 3. Publish provenance alongside artifacts to your registry. 4. Enforce policy verification in staging and prod clusters. 5. Monitor OSS Rebuild logs for dependency anomalies.

"

Provenance without verification is just metadata. Verification without policy is just noise.

— SLSA Working Group

✦

Start today: add the generator action to your next release workflow. The binary you ship tomorrow will carry proof it hasn't been tampered with — proof your incident response team will thank you for.

Share𝕏 Twitterin LinkedInin Whatsapp