Skip to content
Learni
View all tutorials
Sécurité

How to Implement the SLSA Framework in 2026

Lire en français

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

setup.sh
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 main

This 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

main.go
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

.github/workflows/slsa-level1.yml
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+attestation

This 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

verify.sh
#!/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.attest

This 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

.github/workflows/slsa-level2.yml
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

.github/dependabot.yml
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: false

Enables 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-verifier in 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