Skip to content

Latest commit

 

History

56 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

A reusable, profile-extensible SLSA provenance builder foundation.

Contents

Purpose and goals

slsa-builder is a clean, modern, profile-extensible foundation for trusted SLSA provenance builders with a small, auditable trusted computing base (TCB). As a spiritual successor to slsa-github-generator, it carries on the original intent and philosophy without inheriting the legacy surface. Its goal is to freshly implement and support SLSA Build L3+ release workflows for diverse language and registry ecosystems, against the latest SLSA v1.2 specification.

slsa-builder started as a project to meet Windlass's supply-chain security policies, standards, and goals, and it can be broadly useful beyond Windlass to all of the target users described below.

What is SLSA?

SLSA (Supply-chain Levels for Software Artifacts, "salsa") is a security framework: a checklist of standards and controls to prevent tampering, improve integrity, and protect packages and infrastructure. It is a means of securing the highest feasible resilience at every step of the supply chain, going beyond merely being "safe enough."

Supply-chain Levels for Software Artifacts, or SLSA (“salsa”), is a set of incrementally adoptable guidelines for supply chain security, established by industry consensus. The specification set by SLSA is useful for both software producers and consumers: producers can follow SLSA’s guidelines to make their software supply chain more secure, and consumers can use SLSA to make decisions about whether to trust a software package.

https://slsa.dev/spec/v1.2/about

SLSA is described in terms of tracks and levels. Each SLSA track focuses on a particular aspect of the supply chain; as of v1.2 there is a Build track and a Source track.

Within each track, a higher level means a stronger security posture. Higher levels guarantee stronger defense against supply-chain threats, at a higher implementation cost. Lower SLSA levels are designed for easy adoption but provide limited guarantees. "SLSA 0" is sometimes used to describe software that does not yet meet any SLSA level. The SLSA build track currently spans Build L1 through L3, and the official SLSA site states that higher levels are planned for future revisions.

Combining tracks and levels makes it easy to state whether software meets a specific set of requirements. Saying that an artifact meets SLSA Build L3 means that the software artifact was built in accordance with a set of security practices that industry experts recognize as effective at preventing specific supply-chain compromises.

What is provenance?

Provenance is metadata about how a software artifact was produced. It can include information about the source code used, the build system, and the build steps — and even who initiated the build and why. Provenance can be used to judge the authenticity and trustworthiness of the software artifacts you use.

SLSA defines a provenance format for recording this metadata. slsa-builder is a tooling foundation for building and distributing software artifacts in a way that meets SLSA Build L3, and that includes automatically issuing and distributing appropriate provenance under the in-toto attestation framework and the SLSA build provenance v1 format("predicateType": "https://slsa.dev/provenance/v1").

Caution

As the Mini Shai-Hulud supply-chain attack of May 11, 12026 shows, provenance and signatures are necessary conditions for safety, not sufficient ones. Provenance is only one component of the SLSA framework. If the build platform that builds a software artifact and issues its provenance is itself compromised by an attacker, compromised packages can end up being distributed with cryptographically "validly signed" provenance. The packages compromised in the Mini Shai-Hulud incident were using npm's OIDC Trusted Publishing and built-in provenance, which correspond to SLSA Build L2, but the build-environment isolation corresponding to SLSA Build L3 was not in place.

SLSA Build L2 is by no means meaningless — it is far safer than L0 or L1 — but there is a meaningful gap between Build L2 and L3, and it is worth understanding exactly what that gap is and the limits it implies. The following articles may help:

Who it is for

As the official SLSA overview states, SLSA targets software producers, consumers, and infrastructure providers, and it broadly helps anyone who produces, supplies, or distributes packages. For producers, it offers protection against supply-chain tampering, reduced insider risk, and assurance that software reaches consumers as intended — along with a common vocabulary for communication, an actionable checklist, a measure of SSDF alignment, and clearer shared expectations between suppliers and consumers.

slsa-builder can help this same broad SLSA audience, and it is especially useful if one or more of the following applies to you:

  1. Repository maintainers, release workflow authors, and package publishers.
  2. Advanced users who compose workflows from producer and publisher primitives.
  3. Downstream verifiers who use the release manifest, verification policy, and fixtures.

How it works

A thin trusted core works together with profile-owned reusable GitHub Actions workflows. Producer and publisher profiles — and, within a profile, each task (build, sign, publish, and so on) — run isolated with distinct permissions. Producers build artifacts and SLSA provenance, then hand them off to a publisher, which verifies and distributes them. The handoff includes digest and provenance verification, and the procedure aborts immediately if a problem is detected. A signed release manifest maps release versions to workflow SHAs, builder.id values, and buildType URIs.

The exact, observable behavior of each contract outlined in this section is defined in the following technical specifications:

Why should I choose slsa-builder?

slsa-builder aims to meaningfully lower the barrier to adopting the SLSA security framework for members of diverse language and package-registry ecosystems, and to contribute to ecosystem supply-chain security by more broadly disseminating and encouraging SLSA Build L3+ package-distribution practices (see ADR 0001 and ADR 0002). Other existing tools remain useful within their intended scopes, but slsa-builder's strength is providing one integrated, profile-owned trust contract — spanning build, provenance, publishing, distribution, and verification — with a low adoption barrier.

Limitations of existing alternatives

The SLSA get-started guide recommends starting at the highest feasible level from the outset to avoid unnecessary rework. On the GitHub Actions platform, SLSA Build L3 is achievable with a properly designed and configured trust boundary, but existing alternatives have the following limitations.

Strengths of slsa-builder

  • Low-barrier SLSA adoption meeting Build L3 requirements: As covered above, meeting Build L3's provenance-forgery-resistance and build-isolation requirements calls for an isolated reusable workflow in a repository separate from the target package, and designing and maintaining that trust boundary yourself can feel like a burden for each repository maintainer. slsa-builder designs this boundary for you as profile-owned reusable workflows, offered as a paved road to SLSA Build L3. From a caller workflow, a uses: reference and a handful of inputs such as package-directory bring build, provenance issuance, signing, publishing, and verification in as a single contract. Workflow references can be pinned to commit SHAs instead of tags — avoiding the tag-based-reference limitation noted earlier — and provenance follows the latest SLSA v1.2 specification. The goal is to carry forward, on top of the current specification, the low-barrier model that slsa-github-generator demonstrated on GitHub (ADR 0002, ADR 0003, ADR 0023, ADR 0028; spec: JS/TS npm package profile).
  • Minimized trust surface: Rather than inheriting slsa-github-generator's broad legacy and BYOB framework surface, slsa-builder chose a completely fresh start and a smaller, deliberately selected trust surface (ADR 0001, ADR 0002, ADR 0003; spec: Core profile contract).
  • Canonical provenance semantics: slsa-builder records the profile's builder.id, buildType, externalParameters, subject, digest, publish, and verification semantics, and assembles and signs exact Statement bytes with a Go-native Sigstore DSSE signer. A single subject can also carry both SHA-256 and SHA-512 digests over the same tarball bytes, which provides better compatibility than tools that support only a single digest output per subject (ADR 0029, ADR 0042, ADR 0064, ADR 0077; spec: SLSA provenance v1, Identity and build types).
  • End-to-end release trust: Strict signed-JSON handling, immutable builder and source binding, Rekor-backed offline verification with a governed trust root, a signed release manifest, provenance-gated release-asset publishing, and controlled release mutation — all connected end-to-end from source build to release distribution (ADR 0031, ADR 0049, ADR 0050, ADR 0051, ADR 0053, ADR 0061, ADR 0066, ADR 0067, ADR 0068, ADR 0069, ADR 0072, ADR 0073, ADR 0074, ADR 0075, ADR 0076; spec: Release manifest, GitHub Release asset publisher, Verification policy and fixtures).
  • Improved flexibility in release-target tag selection and retry: A release that fails because of a pipeline defect can be retried by dispatching from the ref that carries the fixed pipeline (for example main), while the built and attested content remains the signed release tag. The optional, tags-only source-ref input keeps provenance anchored to the tag's commit, and the dispatch ref is recorded separately as auditable invocation context — closing a gap the predecessor ecosystem never shipped (ADR 0079, ADR 0080; spec: JS/TS npm package profile).

Features

slsa-builder currently provides issuance, distribution, and verification of SLSA provenance for JS/TS packages, GitHub Releases, and npm. Choose the profile that matches your ecosystem and distribution target, and reference it from a caller workflow. Support for additional ecosystems and distribution targets will continue to be added over time.

Provenance issuance and publishing

Ecosystem Profile Description Status
JS/TS npm JS/TS npm package profile npm package build, SLSA v1 provenance issuance and signing, npm publish Pre-release
  • Exactly one package per run: Select the target package with the required package-directory input. The public contract consists of this one required input and eight optional inputs.
  • Fixed-pipeline release retry: The optional, tags-only source-ref input lets a caller retry a failed release by dispatching from a ref that carries the fixed pipeline (for example main) while the built and attested content remains the signed release tag — no retagging, no weakened provenance claim. Provenance records the built tag identity, and the dispatch ref is recorded separately as invocation context (see ADR 0079 and ADR 0080).
  • Manifest-first package manager selection: Supports npm, pnpm, and Yarn Berry v4+ through Corepack, and runs build scripts only when declared (see JS/TS npm build and pack).
  • Secretless trusted publishing: Authenticates with npm OIDC trusted publishing, so no long-lived publish secrets are needed. The SLSA v1 provenance slsa-builder generates carries both SHA-512 and SHA-256 digests of the same tarball bytes in a single npm Package URL subject, is signed with the Go-native Sigstore DSSE signer, and is published through a three-job publish graph (see JS/TS npm provenance and publish).

Release-asset mode

Uploads the built tarball and its provenance sidecar (tarball.intoto.jsonl) to an existing GitHub Release after digest verification (see npm-to-release-asset composition).

Provenance verification

For downstream verifiers, slsa-builder provides a verification policy schema, a fixture taxonomy, and reference commands. The initial profiles do not include a standalone verifier CLI (see Verification policy and fixtures).

Security and trust model

slsa-builder's trust model starts from the premise that "signed provenance is a necessary condition for safety, not a sufficient one". This section summarizes which threats slsa-builder defends against, which external parties it must trust, and where the limits of its defense lie.

Key management and signing

  • No long-lived secrets: npm publish authentication uses OIDC trusted publishing, so no publish tokens need to be stored in the repository (ADR 0024).
  • Keyless signing: Signing uses Sigstore (Fulcio short-lived certificates and OIDC workload identity), so the operational burden of issuing, storing, and rotating private keys disappears entirely. Assembling and signing the exact Statement bytes is handled by the Go-native Sigstore DSSE signer (ADR 0077).
  • Strict signed bytes: Duplicate members in signed JSON are rejected, preventing parser differentials from splitting the signed byte payload (ADR 0061).

Verification model

  • Immutable identity binding: Verification binds to the builder.id of a commit-SHA-pinned workflow and to an immutable source identity, not to movable tags (ADR 0068). Source expectations bind to the signed provenance fields, while the signing certificate's platform-fixed source claims authenticate the invocation context — the two stay cryptographically bound even when a dispatch retry builds a tag from a different invocation ref (ADR 0080).
  • Transparency log and governed trust root: Every signature must be recorded in the Rekor transparency log, and the Sigstore trust root uses a pinned copy governed by the project, enabling offline verification (ADR 0069).
  • Dual digests: A single subject carries both SHA-512 and SHA-256 over the same tarball bytes, supporting verification paths that require different digest algorithms (ADR 0064).
  • The verification policy schema, fixture taxonomy, and reference commands are defined in Verification policy and fixtures.

Release integrity

  • Signed release manifest: A manifest mapping release versions to workflow SHAs, builder.id, and buildType is signed across a three-job signing boundary (ADR 0031, ADR 0053).
  • Provenance-gated publishing: The publisher distributes only after verifying the producer's provenance and digests; unverified bytes are never distributed (ADR 0049, ADR 0050, ADR 0051).
  • Controlled release mutation: Release mutations are serialized with job-class concurrency, and repeated runs within the same run converge to the same result (ADR 0066, ADR 0067).

Trust boundary and dependencies

slsa-builder places trust in GitHub Actions (hosted runners and the OIDC provider), Sigstore (Fulcio, Rekor), and the npm registry. It satisfies SLSA Build L3's isolation requirement by separating build and signing into reusable workflows in a repository different from the caller workflow (ADR 0028). The project is SLSA Build L3-oriented.

Reporting vulnerabilities

Please report security vulnerabilities through the channel described in the Windlass security policy, not via public issues.

Project status and scope

Pre-release. The repository contains a real Go implementation, but the project does not yet claim a stable release; workflow interfaces may change before the first stable version.

Initial non-goals:

  • Generic files or containers.
  • A standalone verifier CLI.
  • Custom-token or PAT release mutation.
  • Raw file uploads without producer provenance.
  • First publication of a brand-new npm package identity.
  • Private dependency credentials as publish credentials.

Spread the word

Whether it is an introduction, an endorsement, or constructive criticism pointing out problems and areas for improvement, the more content — articles, videos, and the like — about slsa-builder and the SLSA framework, the more we can raise awareness of the framework and these tools across the ecosystem and drive adoption. Contributions and feedback are always welcome (contributing guidelines, issue tracker).

There is also a much simpler way to help slsa-builder. If your project uses or supports slsa-builder, spread the word by linking to the project from your README or other project pages. We provide several kinds of badges for inclusion in a README or similar project documentation.

The badges are static SVGs that include the project logo, stored in assets/badges/. Because this repository serves them directly instead of going through an external badge service such as shields.io, the full-color logo is preserved and the badge assets are versioned together with the project. Copy the snippets below as-is, or copy the SVG files and host them yourself. Replace main in the snippet URLs with a release tag or commit SHA to pin an immutable reference.

built with slsa-builder

For projects that build and distribute artifacts with slsa-builder.

built with slsa-builder

Markdown:

[![built with slsa-builder](https://raw.githubusercontent.com/windlasstech/slsa-builder/main/assets/badges/built-with-slsa-builder.svg)](https://github.com/windlasstech/slsa-builder)

HTML:

<a href="https://github.com/windlasstech/slsa-builder"
  ><img
    src="https://raw.githubusercontent.com/windlasstech/slsa-builder/main/assets/badges/built-with-slsa-builder.svg"
    alt="built with slsa-builder"
/></a>

verified with slsa-builder

For downstream verifiers that verify releases with slsa-builder's verification policy and fixtures.

verified with slsa-builder

Markdown:

[![verified with slsa-builder](https://raw.githubusercontent.com/windlasstech/slsa-builder/main/assets/badges/verified-with-slsa-builder.svg)](https://github.com/windlasstech/slsa-builder)

HTML:

<a href="https://github.com/windlasstech/slsa-builder"
  ><img
    src="https://raw.githubusercontent.com/windlasstech/slsa-builder/main/assets/badges/verified-with-slsa-builder.svg"
    alt="verified with slsa-builder"
/></a>

slsa-builder logo badges

Single-background logo badges for simply pointing to the project, provided in two colors: gray (default) and green.

slsa-builder slsa-builder (green)

Markdown:

[![slsa-builder](https://raw.githubusercontent.com/windlasstech/slsa-builder/main/assets/badges/slsa-builder.svg)](https://github.com/windlasstech/slsa-builder)
[![slsa-builder (green)](https://raw.githubusercontent.com/windlasstech/slsa-builder/main/assets/badges/slsa-builder-green.svg)](https://github.com/windlasstech/slsa-builder)

HTML:

<a href="https://github.com/windlasstech/slsa-builder"
  ><img
    src="https://raw.githubusercontent.com/windlasstech/slsa-builder/main/assets/badges/slsa-builder.svg"
    alt="slsa-builder"
/></a>
<a href="https://github.com/windlasstech/slsa-builder"
  ><img
    src="https://raw.githubusercontent.com/windlasstech/slsa-builder/main/assets/badges/slsa-builder-green.svg"
    alt="slsa-builder"
/></a>

Style variants

Each badge is provided in four styles, similar to shields.io. The default flat is provided without a suffix; the other styles are distinguished by a filename suffix.

Style Filename example Preview
flat (default) built-with-slsa-builder.svg built with slsa-builder — flat
flat-square built-with-slsa-builder-flat-square.svg built with slsa-builder — flat-square
plastic built-with-slsa-builder-plastic.svg built with slsa-builder — plastic
for-the-badge built-with-slsa-builder-for-the-badge.svg built with slsa-builder — for-the-badge

The same suffix rule applies to the verified-with-slsa-builder and slsa-builder badges. For the green variant of the logo badge, the color suffix comes before the style suffix (e.g., slsa-builder-green-for-the-badge.svg). For example, a for-the-badge style Markdown snippet looks like this:

[![built with slsa-builder](https://raw.githubusercontent.com/windlasstech/slsa-builder/main/assets/badges/built-with-slsa-builder-for-the-badge.svg)](https://github.com/windlasstech/slsa-builder)

Specifications and ADRs

See the architecture index and the ADR index. ADRs record the rationale in MADR format, while architecture specifications define exactly observable behavior.

Development setup

This repository uses mise to install and pin the development-tool runtime versions. Go is the primary implementation language; Node.js and pnpm are used only for development tooling such as Prettier and Lefthook.

Prerequisites

  • mise installed
  • Git with a configured user name and email

Bootstrap

mise install
pnpm install

This installs the pinned versions of Go, Node.js, pnpm, and the CLI tools defined in mise.toml. Lefthook hooks are installed automatically as a postinstall step when mise installs Lefthook. The pnpm install step then installs the project-local development dependencies declared in package.json.

In CI, run mise with locked mode to avoid API calls to registries:

MISE_LOCKED=1 mise install
pnpm install

After bootstrap, the following commands are available through mise:

go version
node --version
pnpm --version
golangci-lint --version
shellcheck --version
shfmt --version
lefthook --version
actionlint --version

What mise installs versus what pnpm installs

mise installs language runtimes and standalone CLI binaries:

  • Go, Node.js, and pnpm
  • golangci-lint, shellcheck, shfmt, lefthook, actionlint

Go source formatting and import normalization is handled by golangci-lint formatters (gofmt, goimports), configured in .golangci.yml, rather than by standalone formatter binaries.

pnpm installs Node.js-based development dependencies that are coupled to repository configuration files:

  • prettier (configured by .prettierrc)
  • markdownlint-cli2 (configured by .markdownlint-cli2.jsonc)

Keeping Prettier and markdownlint-cli2 as project-local pnpm dependencies preserves their full dependency graph in pnpm-lock.yaml and keeps them aligned with editor integrations and the organization's dependency-review workflow.

Tool versions

Tool versions are declared in mise.toml. A mise.lock file is committed to ensure reproducible installs across platforms. If you change a tool version in mise.toml, regenerate the lockfile with:

mise lock

Commit conventions and sign-off

This project requires a Signed-off-by: trailer on every commit (DCO). Lefthook is configured to enforce this locally, while CI and branch protection perform the authoritative verification.

Contributors

Thanks to everyone who has contributed to this project. You can find the list of contributors on the GitHub contributors graph.

Contributors

License

Distributed under the Apache License 2.0.

About

No description, website, or topics provided.

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages