Introduction
SLSA (Supply-chain Levels for Software Artifacts) is an open-source framework designed to secure software supply chains against attacks like malicious code injections or dependency compromises. Developed by Google and adopted by giants like GitHub, it defines maturity levels (1 to 4) to guarantee tamper-evidence (impossible to alter without detection) and transparency of builds.
Why implement it in 2026? Incidents like SolarWinds or Log4Shell have shown the risks of supply chains. SLSA Level 1, accessible to beginners, already protects against 80% of common threats by making your artifacts (binaries, containers) verifiable via cryptographic provenance attestations. This tutorial guides you step by step for a simple Go project on GitHub Actions: from setup to secure build. Result: a workflow producing a binary + SLSA provenance, publicly verifiable. Ideal for freelancers or startups in DevSecOps. (142 words)
Prerequisites
- Free GitHub account
- Git installed locally
- Go 1.21+ (optional, for local tests; Actions installs it)
- Basic GitHub knowledge (push/pull)
- 10 minutes for a test repo
Initialize the Go project
mkdir slsa-demo
cd slsa-demo
go mod init github.com/votreuser/slsa-demo
go mod tidy
git init
git add .
git commit -m "Initial commit"
gh repo create slsa-demo --public --source=. --remote=origin --push
rm -rf .git
git remote add origin https://github.com/votreuser/slsa-demo.git
git branch -M main
git push -u origin mainThis script initializes an empty Go module, commits it, and pushes to a new public GitHub repo using the gh CLI (install with brew install gh or equivalent). Replace votreuser with your username. This creates a non-forkable base, a SLSA Level 1 requirement. Avoid forks to prevent upstream attacks.
Step 1: Add the main source code
Now create a simple Go 'hello world' program that will serve as the artifact to build. This main.go file will be built reproducibly.
Create the hello world program
package main
import (
"fmt"
"os"
)
func main() {
if len(os.Args) > 1 {
fmt.Printf("Hello, %s! SLSA Level 1 build.\n", os.Args[1])
} else {
fmt.Println("Hello, World! SLSA Level 1 build.")
}
}This Go code compiles into an executable binary. It accepts an argument for customization (test with ./demo hello). Simple and deterministic: no timestamps or randomness, key for SLSA reproducibility. Commit and push: git add main.go; git commit -m 'Add main.go'; git push.
Step 2: Set up the SLSA Level 1 workflow
SLSA Level 1 ensures a tamper-evident build via a locked-down GitHub Actions workflow. Use the official slsa-framework/slsa-github-actions action to automatically generate provenance (encrypted JSON attestation).
SLSA Level 1 build and release workflow
name: SLSA Level 1 Build and Release
on:
push:
tags:
- 'v*'
permissions:
contents: read
id-token: write
jobs:
build:
runs-on: ubuntu-latest
outputs:
provenance_artifact: ${{ steps.provenance.outputs.provenance_artifact }}
container:
image: golang:1.21
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
fetch-depth: 0
- name: Build
run: go build -o demo ./
- uses: slsa-framework/slsa-github-generator/slsa-build@v1
with:
build-target: ./demo
provenance-name: "slsa-demo"
release:
needs: build
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/download-artifact@4
with:
name: slsa-provenance
path: provenance
- uses: actions/create-release@0cb9b9b65be46c690df5f06b0e62e6e2a2de8b1f # v1.1.4
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: Release ${{ github.ref }}
draft: false
prerelease: false
- uses: actions/upload-release-asset@0bc79d5661a4a4ec3a5e6f4d8d5e1f1a2f2f0d2e # v1.0.3
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./demo
asset_name: demo
asset_content_type: application/octet-stream
- uses: actions/upload-release-asset@0bc79d5661a4a4ec3a5e6f4d8d5e1f1a2f2f0d2e # v1.0.3
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./provenance/${{ needs.build.outputs.provenance_artifact }}
asset_name: demo.provenance.attest
asset_content_type: application/vnd.in-toto+json+attestationThis workflow triggers on v* tags, builds the Go binary in an isolated container, generates SLSA attestation via slsa-build, and releases the artifact + provenance to GitHub. Minimal permissions (id-token: write for OIDC). Level 1 validated: non-forkable, logged source, in-container build. Push to test.
Step 3: Test the workflow
Create a tag and push: git tag v1.0.0; git push origin v1.0.0. Go to Actions > this workflow. Success? Download the release, check the binary and demo.provenance.attest attestation.
Local SLSA verification script
#!/bin/bash
# Téléchargez depuis GitHub release
curl -L -o demo https://github.com/votreuser/slsa-demo/releases/download/v1.0.0/demo
curl -L -o demo.provenance.attest https://github.com/votreuser/slsa-demo/releases/download/v1.0.0/demo.provenance.attest
# Vérifiez exécution
chmod +x demo
./demo Learni
# Installez slsa-verifier (go install sigs.dev/slsa/verifier/cmd/slsa-verifier@v2024...)
go install sigs.dev/slsa/verifier/cmd/slsa-verifier@v20240311
# Vérifiez SLSA niveau 1
slsa-verifier demo.provenance.attest \
--source-github-repo votreuser/slsa-demo \
--source-tag v1.0.0 \
--source-digest sha256:$(sha256sum demo | cut -d' ' -f1)
rm demo demo.provenance.attestThis script downloads the artifact and provenance, runs the binary, then uses slsa-verifier to validate the chain: source repo, tag, digest. Replace votreuser with your username. If 'VERIFIED', SLSA Level 1 is good. Install Go for slsa-verifier. Pitfall: wrong digest fails.
Step 4: Upgrade to SLSA Level 2
Level 2 adds scripted builds and Dependabot. Add a file to lock down actions.
Action pinning for SLSA Level 2
name: SLSA Level 2 Enhanced
on:
push:
tags:
- 'v*'
permissions:
contents: read
id-token: write
jobs:
build:
runs-on: ubuntu-latest
container:
image: golang:1.21@sha256:abcd123... # Pin image
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # pin v4.1.7
- uses: slsa-framework/slsa-github-generator/slsa-build@v1.8.0 # pin
with:
build-target: ./demo
provenance-name: "slsa-demo-level2"
release:
needs: build
runs-on: ubuntu-latest
steps:
- id: provenance
uses: actions/download-artifact@v4
with:
path: ./
pattern: slsa-provenance
- uses: actions/create-release@v1
with:
tag_name: ${{ github.ref }}
release_name: Level 2 ${{ github.ref }}
# ... (similaire à précédent, avec pins)Upgraded version with SHA pins on actions/images (use .github/dependabot.yml for auto-updates). Adds scripted steps, a SLSA Level 2 prerequisite. Copy-paste after Level 1, tag v2.0.0. Prevents supply chain attacks via pinning. Verify as before.
Dependabot for secure updates
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 10
rebase-strategy: auto
groups:
slsa-actions:
patterns:
- "slsa-framework/*"
update-types:
- "semver:major"
- "semver:minor"
- "semver:patch"
- "version-update:semver:major"
- "version-update:semver:minor"
- "version-update:semver:patch"
security-updates-only: falseEnables Dependabot to automatically update SLSA actions via PRs. SLSA group for prioritization. Level 2 requires controlled updates. Commit and enable in repo Settings > Dependabot.
Best practices
- Always pin actions/images by SHA, not tags (vulnerable to hijacks).
- Use OIDC (
id-token: write) instead of GITHUB_TOKEN secrets for cosign/rekord. - Enable branch protection: require PR reviews, no direct pushes to main/tags.
- Test regularly with
slsa-verifierin CI. - Migrate to Level 3+ for fully hermetic builds (no network during build).
Common errors to avoid
- Forgetting fetch-depth: 0: breaks git history verification.
- Pushing from a fork: SLSA requires owner repo, non-forkable.
- No container: build contaminated by host, fails Level 1.
- Ignoring provenance: always download the attestation with the artifact.
Next steps
- Official docs: SLSA Framework
- SLSA GitHub Generator: GitHub Repo
- Verify levels: SLSA Verifier
- Advanced DevSecOps training: Discover our Learni trainings
- Next: SLSA for Docker/K8s with Cosign.