Software Supply Chain Security and the SLSA Framework in GitHub

Software Supply Chain Security and the SLSA Framework in GitHub

A complete, beginner-friendly guide to how modern software actually gets built, why attackers love the build pipeline more than the code itself, and how SLSA and GitHub's native tooling close that gap — explained from first principles, with real incidents and production patterns.

In 2020, a routine software update from a well-known IT management vendor was quietly modified before it ever reached customers. Nobody broke into the customer’s network. Nobody guessed a password. The attackers simply got inside the build process — the invisible machinery that turns source code into the software you install — and let the vendor’s own trusted update mechanism carry the malware in for them. Roughly eighteen thousand organizations installed it without a second thought, because it came from a name they trusted, signed and shipped through a pipeline they had never once questioned. That single event reshaped how the entire software industry thinks about security, and it is the reason a framework called SLSA, and a platform called GitHub, now sit at the center of how trustworthy software gets built. This guide walks through that whole story: what a software supply chain actually is, how it gets attacked, what SLSA does about it, and exactly how GitHub turns those ideas into features you can turn on today.

AWhat Is Software Supply Chain Security?

Before SLSA makes sense, the term “supply chain” itself needs to stop feeling abstract. It is not a diagram in a slide deck — it is every single hand that touches your code between the moment a developer types it and the moment a user runs it.

A software supply chain is the complete sequence of people, systems, and processes involved in creating a piece of software: the developers who write code, the open-source libraries that code depends on, the build servers that compile it, the registries that host it, and the systems that deploy it into production. Just like a physical product — say, a car — passes through raw material suppliers, parts manufacturers, an assembly line, and a dealership before reaching a driver, software passes through source code, third-party dependencies, a build pipeline, a package registry, and a deployment target before reaching a user.

Software supply chain security is the discipline of protecting every one of those links so that the software a user finally installs is exactly the software the original developers intended — nothing added, nothing swapped, nothing tampered with along the way.

Everyday Analogy

Think about ordering a sealed bottle of medicine from a pharmacy. You trust it not because you watched every step of manufacturing yourself, but because tamper-evident seals, batch tracking, and regulated factories give you confidence that nobody opened the bottle and swapped the pills between the factory and your hand. Software supply chain security tries to build that same tamper-evident seal around code — a cryptographic guarantee that what left the factory (the build system) is exactly what arrived in your hands (your production server).

The reason this discipline exploded in importance over the last several years is simple: modern applications are assembled, not written. A typical production application might contain a few thousand lines of code its own developers actually wrote, sitting on top of hundreds of thousands of lines pulled in from open-source packages, each of which was written by someone the development team has never met and will never audit line by line. Attackers noticed this imbalance long before most companies did. Instead of trying to find a bug in one company’s carefully reviewed code, it is far more efficient to poison one popular open-source package, or one shared build pipeline, and let thousands of downstream applications inherit the malicious code automatically the next time they run a routine update.

!
Why This Matters Now

Supply chain attacks do not require breaking your defenses. They require breaking someone else’s defenses — a library maintainer, a build server, a CI/CD pipeline — and then simply waiting for your systems to trust that broken link automatically.

The Three Questions Supply Chain Security Answers

Every meaningful supply chain security control ultimately answers one of three questions about a piece of software:

PROVENANCE

Where did this come from?

Which source repository, which commit, which build system, and which exact build steps produced this artifact.

INTEGRITY

Has it been altered?

Whether the artifact you received is byte-for-byte the same thing the build system actually produced, with no tampering in transit or in storage.

IDENTITY

Who is vouching for it?

Which organization, system, or individual cryptographically signed off on this artifact as trustworthy for use.

Every concept in this guide — provenance attestations, SLSA levels, GitHub’s build attestation feature, Sigstore signing — exists purely in service of answering those three questions with something stronger than “we assume it’s fine.”

BAnatomy of a Software Supply Chain

To defend a supply chain, you first need to see all of its links laid out — because attackers only need to find one weak one.

A modern supply chain has five broad stages, and a vulnerability introduced at any single stage can silently propagate to every stage after it.

flowchart LR
    A[Developer Writes Code] --> B[Source Repository]
    B --> C[Third-Party Dependencies]
    C --> D[Build System / CI Pipeline]
    D --> E[Build Artifacts]
    E --> F[Package Registry]
    F --> G[Deployment Environment]
    G --> H[Production / End Users]
    

FIG 1 — The five stages of a software supply chain, source through production

Stage 1: Source Code

This is the code your own developers write, stored in a version control system such as a Git repository. Threats here include a compromised developer account pushing malicious commits, a stolen personal access token, or a weakly protected main branch that allows unreviewed changes to merge directly.

Stage 2: Dependencies

Almost no application is built from scratch. It pulls in open-source libraries through package managers — npm for JavaScript, pip for Python, Maven for Java, and dozens of others. Each dependency can itself depend on further dependencies, forming what is called a transitive dependency tree that can reach thousands of packages for a single application, most of which nobody on the team has ever reviewed.

Stage 3: Build System

This is the machinery — typically a continuous integration and continuous delivery (CI/CD) pipeline such as GitHub Actions, Jenkins, or CircleCI — that compiles source code and dependencies into a runnable artifact: a binary, a container image, a compiled package. The build system is one of the highest-value targets in the entire chain, because compromising it lets an attacker inject malicious code into every artifact it produces, without ever touching the source repository at all.

Stage 4: Artifact Registry

Once built, artifacts are published to a registry — npm’s registry, PyPI, Docker Hub, or a private container registry — where other systems and developers can download them. A compromised registry account, or a registry that fails to verify who is allowed to publish under a given package name, lets an attacker distribute malicious versions directly to consumers.

Stage 5: Deployment

Finally, the artifact is deployed into a running environment — a Kubernetes cluster, a set of virtual machines, a serverless platform. Deployment credentials, infrastructure-as-code templates, and the deployment pipeline itself are all part of the chain that must be protected.

Why Attackers Prefer the Build System

Compromising a single developer’s laptop yields one person’s future commits. Compromising a shared build system yields every artifact that system will ever produce, for every team that uses it, indefinitely — until someone notices. This asymmetry is exactly why build-system compromise has become the signature technique behind the largest supply chain attacks of the last decade.

CHow Supply Chain Attacks Actually Happen

Supply chain attacks fall into a handful of repeatable patterns. Recognizing the pattern is the first step toward defending against it.

Dependency Confusion

Many companies use internal, privately named packages alongside public ones. If an attacker publishes a public package with the exact same name as a company’s private internal package, and the build tooling is not configured to prioritize the private registry, developers’ machines and build servers can silently pull down the attacker’s public, malicious version instead of the trusted internal one — because higher version numbers on public registries are often preferred by default.

Typosquatting

Attackers publish packages with names deliberately similar to popular ones — a single transposed letter, a missing hyphen — betting that a developer will mistype an install command and pull in malware instead of the legitimate library.

Compromised Maintainer Accounts

Popular open-source packages are often maintained by one or two volunteers. If an attacker phishes or brute-forces a maintainer’s registry credentials, they can push a malicious update directly to a package that millions of applications already trust and auto-update from — no code review, no pull request, straight to production for everyone downstream.

Build System Compromise

Rather than touching the source code at all, an attacker who compromises the build environment can inject malicious steps into the build process itself — modifying compiler flags, injecting a malicious build script, or tampering with the output artifact after legitimate compilation finishes but before it is signed and published. Because the source code repository looks completely clean under review, this is one of the hardest attack patterns to detect through code review alone.

Malicious Third-Party CI Actions and Plugins

CI/CD platforms like GitHub Actions allow pipelines to call reusable, community-published building blocks. If a pipeline references a third-party action by a mutable tag such as a branch name rather than a fixed, immutable commit hash, the maintainer of that action — or anyone who compromises their account — can silently swap in malicious behavior that every pipeline referencing that tag will execute on its very next run.

1
COMPROMISED LINK CAN POISON THOUSANDS OF DOWNSTREAM APPS
Weeks
TYPICAL TIME BETWEEN INJECTION AND DISCOVERY IN PAST INCIDENTS
0
TRADITIONAL ANTIVIRUS DETECTIONS FOR A SIGNED, TRUSTED UPDATE
i
What An Interviewer May Ask

“Why is a build-system compromise harder to detect than a source-code compromise?” A strong answer explains that source code is reviewed by humans and diffed automatically, but the build process runs unattended, often on ephemeral infrastructure, and its output is judged only by whether the artifact “works” — not by whether every step that produced it was legitimate.

DThe SLSA Framework: Origins and Purpose

SLSA did not appear out of nowhere. It is the industry’s direct, structured answer to exactly the attack patterns described above.

SLSA stands for Supply-chain Levels for Software Artifacts, pronounced “salsa.” It began as an internal framework at Google, built from years of experience hardening their own internal build systems, and was opened up as a cross-industry standard hosted by the Open Source Security Foundation (OpenSSF) so that any organization — not just Google — could adopt a shared, verifiable language for supply chain trust.

SLSA’s core insight is refreshingly simple: instead of trying to inspect every dependency’s source code by hand — an impossible task at the scale of a modern application — focus on making the build process itself trustworthy, verifiable, and tamper-resistant. If you can cryptographically prove exactly how an artifact was built, from exactly which source, on exactly which system, then you no longer need to manually re-verify every artifact’s contents — you can verify its provenance instead.

Everyday Analogy

SLSA is closest in spirit to a food safety certification. A restaurant inspector does not personally taste-test every dish that leaves the kitchen. Instead, they certify that the kitchen’s process — its cleanliness, its sourcing, its handling procedures — meets a defined standard. Once the process is certified, every dish that comes out of it inherits a baseline of trust. SLSA certifies the “kitchen” — the build pipeline — rather than inspecting every individual “dish,” the artifact.

What SLSA Is Not

It is worth being precise here, because this is a common point of confusion. SLSA is not a vulnerability scanner, it does not look for bugs in your code, and it does not replace tools like static analysis or dependency vulnerability scanning. SLSA answers a narrower, foundational question: can you prove how this artifact was built, and can you prove nobody tampered with it afterward? A perfectly secure, bug-free artifact built through an untrustworthy, unverifiable process still fails SLSA’s goals, because there is no way to prove it wasn’t swapped for something else before it reached you.

ESLSA Levels Explained

SLSA is organized as a ladder of four levels, each one adding stronger guarantees than the last. You do not need to reach the top rung immediately — the whole point of a leveled framework is that any step up is measurable progress.

flowchart TD
    S0["SLSA Level 0
    No guarantees — status quo"] --> S1["SLSA Level 1
    Build process is documented and automated"]
    S1 --> S2["SLSA Level 2
    Build runs on a hosted, shared build service; provenance is signed"]
    S2 --> S3["SLSA Level 3
    Build runs in a hardened, isolated environment; provenance is non-forgeable"]
    

FIG 2 — The SLSA build track levels, each one strengthening the guarantees of the level before it

SLSA Level 1: Documented Build Process

At Level 1, the build is scripted and automated rather than done manually on someone’s laptop, and it generates a provenance record — metadata describing what was built, from what source, and by what process. This provenance does not yet need to be cryptographically protected; it simply needs to exist. The value here is basic transparency: anyone can now see how the artifact claims to have been built, even if that claim isn’t yet independently verifiable.

SLSA Level 2: Hosted Build, Signed Provenance

At Level 2, the build must run on a managed, shared build platform — such as GitHub Actions’ hosted runners — rather than on an individual’s personal machine, and the resulting provenance must be cryptographically signed. This closes a major gap: at Level 1, someone could simply fabricate a fake provenance file describing a build that never actually happened. At Level 2, the provenance is generated by the build platform itself, not by the developer, which makes it meaningfully harder to forge.

SLSA Level 3: Hardened, Non-Falsifiable Builds

Level 3 requires the build platform to isolate each build so thoroughly that even a malicious build script cannot tamper with the provenance generation process itself, or influence the builds of other projects running on the same shared infrastructure. This is the level where organizations can trust provenance even against an attacker who has managed to inject malicious code into the build steps, because the provenance-signing process is isolated from — and cannot be manipulated by — the build steps it is describing.

What Higher Levels Buy You

  • Provenance that survives even a compromised build script
  • Verifiable proof of exact source commit and build parameters
  • A basis for automated policy enforcement — “only accept artifacts built at Level 3”

What Higher Levels Cost You

  • More rigid, less flexible build pipeline configurations
  • Requires the underlying build platform to support isolation guarantees
  • Migration effort for legacy pipelines built without provenance in mind
i
What An Interviewer May Ask

“What is the single biggest difference between SLSA Level 1 and Level 2?” The expected answer: Level 1 provenance can be self-reported and therefore forged, while Level 2 provenance is generated and signed by a shared build platform the developer does not fully control, which is what makes it trustworthy to a third party.

Source Track: A Second, Complementary Ladder

Alongside the build track described above, SLSA also defines a source track focused on the trustworthiness of the source repository itself — covering practices like requiring code review before merge, retaining a verifiable history of changes, and preventing history from being silently rewritten. A fully mature SLSA adoption strengthens both the source side and the build side, because a perfectly verified build of tampered source code is still a compromised artifact.

FData Flow: From Source to Verified Deployment

It helps to trace a single artifact’s journey end to end, watching exactly where provenance is created, attached, and finally checked.

1

Commit Is Pushed

A developer pushes a commit, or merges a reviewed pull request, into the source repository. This commit hash becomes the anchor point that provenance will later reference.

2

Build Is Triggered

A CI/CD pipeline is triggered on the hosted build platform. The platform, not the developer’s machine, takes control of the build from this point forward.

3

Artifact Is Compiled

Source code and pinned dependencies are compiled or packaged into a build artifact — a binary, a container image, or a package archive.

4

Provenance Is Generated

The build platform itself — not the build script — generates a provenance statement recording the source commit, the build steps, the builder’s identity, and a cryptographic hash of the resulting artifact.

5

Provenance Is Signed

The provenance statement is cryptographically signed, binding it permanently to the exact artifact hash it describes. Any later modification to the artifact would invalidate the signature.

6

Artifact and Provenance Are Published

Both the artifact and its signed provenance are published together to a registry, ready for consumers to download.

7

Consumer Verifies Before Trusting

Before using the artifact, a consuming system checks the signature, confirms the provenance matches an expected source and builder, and only then allows it to proceed — for example, into a production deployment.

“An unsigned, unverified artifact is a promise. A signed, SLSA-compliant artifact is a receipt.”

The critical shift SLSA introduces is at step 7. Without provenance, “trust” is usually just a habit — a team downloads a package because they always have, with no actual check happening. With provenance in place, trust becomes a verifiable, automatable decision: a deployment pipeline can be configured to mechanically reject any artifact whose provenance does not check out, closing the loop that most organizations previously left wide open.

GAdvantages, Disadvantages, and Trade-offs

Like every security control, SLSA adoption is not free. Understanding the trade-offs helps teams adopt it deliberately rather than reflexively.

ADVANTAGE

Automatable Trust

Provenance checks can be enforced by machines at deploy time, removing reliance on manual, error-prone human review of every dependency.

ADVANTAGE

Blast Radius Containment

If a build system is compromised, higher SLSA levels make it dramatically harder for the attacker to forge convincing, signed provenance, limiting how far the compromise can spread undetected.

ADVANTAGE

Common Industry Language

SLSA levels give vendors, auditors, and customers a shared vocabulary for supply chain maturity, instead of every company inventing its own ad hoc standard.

TRADE-OFF

Engineering Investment

Reaching higher levels requires migrating pipelines to hosted, isolated build platforms and adjusting workflows that were previously more flexible or manual.

TRADE-OFF

Ecosystem Dependency

The guarantees only hold if every link in the chain — including third-party dependencies — eventually adopts compatible provenance practices; a single unattested dependency remains a blind spot.

TRADE-OFF

Not a Silver Bullet

SLSA proves how an artifact was built, not that its logic is free of bugs or vulnerabilities — it must be paired with code review, dependency scanning, and testing, not used as a replacement for them.

HGitHub’s Supply Chain Security Toolset

GitHub has built a set of native features that map almost one-to-one onto the supply chain stages from Chapter B, and onto SLSA’s own requirements. Here is how each piece fits.

Supply Chain StageGitHub FeatureWhat It Protects Against
Source CodeBranch protection rules, required reviews, signed commitsUnauthorized or unreviewed changes reaching the main branch
DependenciesDependabot alerts and version updatesKnown-vulnerable dependency versions being used unknowingly
DependenciesDependency graph and dependency reviewBlind spots in what a project actually depends on, including transitively
Source / SecretsSecret scanning and push protectionCredentials or API keys accidentally committed and exposed
Code QualityCodeQL code scanningExploitable code-level vulnerability patterns introduced by any contributor
Build SystemGitHub Actions hosted runnersBuilds running on untrusted, unmanaged personal machines
Build CredentialsOpenID Connect (OIDC) federated identityLong-lived cloud deployment credentials sitting in repository secrets
ProvenanceArtifact attestations (build provenance)Unverifiable claims about how and where an artifact was actually built

Dependabot: Watching the Dependency Layer

Dependabot continuously compares a repository’s declared dependencies against a database of known vulnerabilities and automatically opens alerts, and optionally pull requests, when a fix is available. This directly addresses the dependency stage of the supply chain — the layer most teams have the least visibility into by default.

Secret Scanning and Push Protection

Secret scanning continuously inspects repository content for patterns that look like exposed credentials — API keys, tokens, private keys — and push protection goes a step further by blocking a commit from ever being pushed if it contains a detectable secret, stopping the leak before it happens rather than only alerting after the fact.

CodeQL: Semantic Code Scanning

CodeQL treats source code as queryable data, allowing automated detection of vulnerability patterns — such as unsanitized input reaching a dangerous function — across an entire codebase, on every pull request, without waiting for a human reviewer to spot the same issue manually.

OpenID Connect: Removing Long-Lived Cloud Secrets

Historically, a CI pipeline that needed to deploy to a cloud provider stored a long-lived access key as a repository secret — a juicy, permanent target if the pipeline was ever compromised. OIDC lets GitHub Actions instead request a short-lived, automatically expiring identity token at run time, which the cloud provider trusts based on a pre-configured relationship with the specific repository and workflow, removing the need for a standing secret altogether.

i
What An Interviewer May Ask

“Why does removing long-lived cloud credentials from CI actually matter?” Because a stolen long-lived key remains valid indefinitely until someone manually revokes it, while a stolen OIDC-issued token typically expires within minutes, sharply limiting how much damage a compromised pipeline can do before the exposure closes itself.

ISLSA in Practice: GitHub Actions Build Provenance

This is where the theory of SLSA levels turns into an actual feature a repository maintainer can switch on.

flowchart LR
    Trigger["Push / Release Tag
    Triggers Workflow"] --> Runner["GitHub-Hosted Runner
    Executes Build Job"]
    Runner --> Build["Source Compiled Into
    Build Artifact"]
    Build --> OIDC["Runner Requests
    OIDC Identity Token"]
    OIDC --> Attest["Build Provenance
    Attestation Generated"]
    Attest --> Sign["Keyless Signing via
    Sigstore / Fulcio / Rekor"]
    Sign --> Store["Attestation Attached
    to the Artifact"]
    Store --> Verify["Consumer Runs
    Attestation Verification"]
    

FIG 3 — How a GitHub Actions build produces a signed, SLSA-aligned provenance attestation

Artifact Attestations

GitHub Actions can generate a build provenance attestation for any artifact produced by a workflow — describing the exact source repository, commit, workflow file, and build environment that produced it. This attestation is generated by the GitHub Actions platform itself at build time, not self-reported by the workflow script, which is exactly the property SLSA Level 2 requires: provenance the developer cannot simply fabricate.

Keyless Signing with Sigstore

Rather than requiring every project to generate, store, and rotate its own private signing key — historically one of the biggest practical barriers to widespread artifact signing — GitHub Actions integrates with Sigstore’s keyless signing model. A short-lived certificate is issued for the specific workflow run, tied to the workflow’s verified OIDC identity, used once to sign the artifact, and then discarded, while a public transparency log permanently and publicly records that the signing event occurred, so it can be independently audited later even after the certificate itself has expired.

Everyday Analogy

Keyless signing is closer to getting a wax seal stamped by a notary who checks your ID on the spot, rather than owning a personal signet ring you must keep locked away forever. The notary’s stamp is trusted because of who verified you in that moment, and a public ledger records that the stamping happened — not because you are personally safeguarding a precious physical object that could be stolen.

Verifying an Artifact’s Provenance

Once an artifact has an attached attestation, anyone downloading it can verify that the artifact’s cryptographic hash matches the one recorded in the signed provenance, that the signature is valid, and that the provenance describes the expected source repository and workflow — turning “I trust this because I downloaded it from the right-looking URL” into “I verified this was built from the exact source I expect, by the exact pipeline I expect.”

Reusable Workflows and Pinned Actions

Two closely related GitHub practices strengthen the build stage further. Reusable workflows let an organization define one hardened, centrally maintained build process and have every project call into it, rather than each team reinventing — and potentially weakening — their own pipeline. Pinning third-party actions to an immutable commit hash, instead of a mutable branch or version tag, ensures that a pipeline always executes the exact code that was reviewed and approved, even if the action’s maintainer later publishes a malicious update under the same tag.

JSecurity Considerations and Threat Models

Provenance and attestations are powerful, but only when they are actually checked, and only when the trust boundaries around them are drawn correctly.

Attestation Without Enforcement Is Just Documentation

Generating a signed provenance attestation accomplishes nothing on its own if nothing downstream ever checks it. Real security value only appears once deployment pipelines or admission controllers are configured to actively reject artifacts that lack valid, expected provenance — turning an available fact into an enforced policy.

The GITHUB_TOKEN and Least Privilege

Every GitHub Actions workflow run is automatically issued a short-lived token scoped to that repository, used to interact with the GitHub API during the run. A workflow that requests broader permissions than it actually needs — write access to other repositories, for example — expands what an attacker could do if that specific workflow run were ever compromised through a malicious dependency or a poisoned third-party action. Scoping permissions down to the minimum a workflow genuinely requires is one of the simplest, highest-value hardening steps available.

Pull Request Workflow Risks

Workflows that automatically run in response to pull requests from external contributors deserve particular care, because an untrusted contributor’s branch can contain code designed specifically to abuse the workflow’s permissions or exfiltrate secrets if the workflow is not carefully scoped and reviewed before it runs with elevated access.

Transitive Trust

An organization’s supply chain security is only as strong as the weakest attestation anywhere in its dependency tree. A perfectly SLSA Level 3 build that pulls in one unattested, unverified third-party dependency still inherits that dependency’s risk — provenance does not automatically propagate backward through a supply chain unless every layer participates.

!
Common Misconception

Signed provenance proves how an artifact was built — it does not prove the artifact is free of vulnerabilities or malicious logic that was present in the source code from the start. A malicious commit, once merged, will produce a perfectly valid, perfectly signed attestation for the malicious build.

KMonitoring, Logging, and Auditability

Prevention alone is never enough; every mature supply chain program assumes something will eventually slip through, and builds the ability to detect and investigate it quickly.

The Transparency Log

Every keyless signing event through Sigstore is recorded in a public, append-only transparency log. This means that even long after a certificate has expired, anyone — including the original developer — can later audit exactly when and under what identity a given artifact was signed, and detect if a signing event occurred that nobody on the team actually initiated.

Workflow Run Logs and Audit Logs

GitHub retains detailed logs of every workflow run, including exactly which steps executed and what permissions were granted, alongside organization-level audit logs covering security-relevant events such as changes to branch protection rules or secret access. Together these give security teams the raw material needed to reconstruct exactly what happened during an incident.

Dependency and Vulnerability Alerts as Continuous Monitoring

Because Dependabot continuously re-checks dependencies against an evolving vulnerability database, a dependency that was safe on the day it was added can later trigger an alert the moment a new vulnerability is disclosed against it — effectively giving every historical build a form of retroactive, ongoing monitoring rather than a one-time check performed only at build time.

Why Immutable Logs Matter

If an attacker who compromises a build system could also quietly edit the logs describing what that build system did, logging alone would offer little real protection. This is precisely why transparency logs are designed to be append-only and independently verifiable — an entry, once written, cannot be silently altered or deleted without the tampering itself becoming detectable.

LDesign Patterns and Anti-patterns

Teams tend to repeat the same handful of good and bad decisions when building out their supply chain security posture. Recognizing them by name speeds up both design reviews and troubleshooting.

Pattern: Provenance-Gated Deployment

A deployment pipeline that automatically refuses to deploy any artifact lacking a valid, expected provenance attestation — turning provenance from a nice-to-have record into an enforced gate that no artifact can bypass, regardless of who or what tries to deploy it.

Pattern: Golden, Centrally Maintained Build Pipeline

A single, security-reviewed reusable workflow, maintained by a central platform team, that every product team calls into rather than assembling their own build steps from scratch — concentrating security investment into one place instead of spreading thin, inconsistent effort across dozens of independently maintained pipelines.

Pattern: Least-Privilege, Just-in-Time Credentials

Using OIDC-issued, short-lived tokens scoped narrowly to exactly what a specific workflow run needs, rather than broad, standing credentials shared across every pipeline in an organization.

Anti-pattern: Trusting Mutable References

Referencing a third-party GitHub Action by a branch name or a mutable version tag rather than a fixed commit hash, which silently allows the code your pipeline executes to change without any review on your side, the moment the action’s maintainer — or anyone who compromises their account — pushes a new commit under that same tag.

PATTERN-001 ANTI-PATTERN
Pattern

Sharing one broad, long-lived cloud deployment credential across every repository and workflow in an organization for convenience.

Why It Feels Reasonable

It avoids the setup overhead of configuring a separate, scoped identity for every individual pipeline.

Why It Fails

A single compromised workflow — through a malicious dependency, a poisoned action, or a leaked log — now grants an attacker the same broad access every other pipeline in the organization enjoys, turning one small breach into an organization-wide one.

Anti-pattern: “Set and Forget” Security Scanning

Enabling scanning tools such as Dependabot or CodeQL once and never actually triaging, prioritizing, or acting on the alerts they generate — which produces the appearance of security maturity without any of its actual benefit, and often trains teams to start ignoring alerts altogether once the backlog grows large enough.

MBest Practices and Common Mistakes

Most of the guidance below is inexpensive to implement and disproportionately effective — the kind of foundational hygiene that closes off the majority of realistic attack paths before more advanced controls are even needed.

BEST PRACTICE

Pin Every Third-Party Action to a Commit Hash

Never trust a mutable tag for code that runs with access to your repository and secrets.

BEST PRACTICE

Scope Workflow Permissions Explicitly

Set the minimum required permissions for the automatically issued token on every workflow, rather than relying on broad defaults.

BEST PRACTICE

Require Reviewed, Protected Branches

Enforce mandatory code review and status checks before any change reaches the branch your builds are triggered from.

BEST PRACTICE

Generate and Verify Build Attestations

Turn on artifact attestations for release builds, and actually verify them at deployment time rather than only generating them.

BEST PRACTICE

Replace Long-Lived Secrets with OIDC

Wherever a cloud provider supports federated identity, prefer short-lived, automatically expiring tokens over standing credentials.

BEST PRACTICE

Triage Dependency Alerts on a Cadence

Treat vulnerability alerts as a recurring operational task with clear ownership, not a dashboard nobody is assigned to check.

Common Mistakes

  • Assuming a private repository is automatically a secure build environment, and skipping supply chain controls entirely because “nobody can see our code.”
  • Granting workflows write access to unrelated repositories “just in case,” rather than scoping access to exactly what each workflow needs.
  • Treating a passing vulnerability scan as proof of safety, when the scan only covers known, previously disclosed vulnerabilities and says nothing about novel or intentionally hidden malicious code.
  • Allowing workflows triggered by external pull requests to run with the same elevated permissions as workflows triggered by trusted, internal changes.

NReal-World Examples

Every concept in this guide traces back to an incident that made it necessary. Studying a few of them makes the abstract framework feel concrete.

1

The event-stream Incident (2018)

A widely used, small JavaScript utility package was handed off to a new “volunteer” maintainer, who then quietly added a malicious dependency designed to steal cryptocurrency wallet credentials from downstream applications — illustrating how maintainer trust itself can be socially engineered and exploited.

2

The SolarWinds Build Compromise (2020)

Attackers gained access to the build environment of a widely used IT management platform and injected malicious code directly into the build process, so that the vendor’s own official, digitally signed software updates carried the malware — an attack that specifically targeted trust in the build system rather than the source code.

3

The Codecov Bash Uploader Compromise (2021)

A widely used CI script, embedded directly into thousands of organizations’ build pipelines, was modified by attackers to exfiltrate environment variables and secrets from every pipeline that executed it — demonstrating how a single popular CI helper script functions as a high-leverage supply chain target.

4

The XZ Utils Backdoor Attempt (2024)

An individual who had spent years building trust as a co-maintainer of a widely depended-upon compression library used that earned trust to introduce a sophisticated, deliberately obfuscated backdoor into the build process — caught unusually early, and widely cited afterward as a case study in exactly why build-process integrity, not just code review, has to be independently verifiable.

“Every major supply chain incident of the last decade targeted trust in a process, not a weakness in a single line of code.”

OFrequently Asked Questions

Q1Is SLSA only relevant to large organizations like Google?
No. SLSA was designed to be adoptable incrementally by projects of any size, and platforms like GitHub Actions provide much of the required infrastructure — hosted runners, OIDC, build attestations — out of the box, meaning even a small open-source project can reach a meaningful SLSA level without building custom infrastructure.
Q2Does reaching SLSA Level 3 mean an application has no vulnerabilities?
No. SLSA is exclusively about the integrity and verifiability of the build process, not about the absence of bugs or vulnerabilities in the code itself. It must be combined with practices like code review, dependency scanning, and testing to address those separate concerns.
Q3What is the difference between provenance and a software bill of materials (SBOM)?
Provenance describes how and where an artifact was built — the process. An SBOM describes what the artifact contains — every component and dependency inside it. They answer different questions and are commonly used together: provenance establishes trust in the build, while the SBOM establishes visibility into the contents.
Q4Why does GitHub use “keyless” signing instead of traditional signing keys?
Traditional signing requires every project to securely generate, store, and rotate a private key forever — a key that becomes a single, high-value target if ever leaked. Keyless signing issues a short-lived certificate tied to a verified workflow identity for a single signing event, removing the burden and risk of long-term key custody entirely.
Q5Can a compromised dependency still pass a SLSA Level 3 build?
Yes. If malicious code exists inside the source or a dependency before the build even starts, a SLSA-compliant build will faithfully and accurately attest to building that malicious code — provenance proves the build was not tampered with in transit, not that everything going into it was safe to begin with.
Q6Is generating a provenance attestation enough on its own?
Not by itself. The real security benefit only materializes once something downstream — a deployment pipeline, an admission controller, a registry policy — actually verifies that attestation and refuses artifacts that fail the check.

PSummary and Key Takeaways

Key Takeaways

  • A software supply chain spans every stage from source code through dependencies, the build system, the registry, and finally deployment — and a compromise at any single stage can silently propagate to everything after it.
  • SLSA (“Supply-chain Levels for Software Artifacts”) makes trust in software verifiable by focusing on the integrity of the build process rather than attempting to manually re-inspect every artifact’s contents.
  • SLSA’s four levels progress from a documented build process, to a hosted build with signed provenance, to a fully hardened build environment where even a compromised build script cannot forge convincing provenance.
  • GitHub’s native tooling — Dependabot, secret scanning, CodeQL, OIDC federated credentials, and build provenance attestations — maps directly onto both the supply chain stages and SLSA’s own requirements, making meaningful adoption achievable without custom infrastructure.
  • Keyless signing via Sigstore removes the historical burden of long-term private key management by issuing short-lived, identity-bound certificates for each signing event, recorded permanently in a public transparency log.
  • Provenance without enforcement is just documentation. The real security value only appears once deployment pipelines are configured to actively verify attestations and reject artifacts that fail the check.
  • Every landmark supply chain incident — from event-stream to SolarWinds to the XZ Utils backdoor — targeted trust in a process rather than a flaw in a single line of code, which is precisely the gap SLSA and GitHub’s attestation tooling were built to close.