>_ DevTrendsen

Language

Home

Languages

Sections

Frontend Backend Mobile DevOps AI / ML GameDev Blockchain Embedded Security
Unknown

How to verify that a GitHub Actions artifact was built by you, not an attacker

Supply chain attacks have long turned from theory into harsh reality. Let's say a user downloads a pre-built binary from the Releases section on GitHub. How can they verify that the file was actually built by the CI server from the source code of a specific commit, and not uploaded by a hacker who gained access to the developer's account?

To solve this problem, GitHub rolled out a special action actions/attest-build-provenance. Let's break down how it works, why Sigstore signatures are needed, and why you'll need a slightly different tool when creating new pipelines.

Where to bind the signature

The essence of provenance signing is quite simple. Every finished file needs a digital passport. This document confirms: the artifact with a specific hash was built inside a specific workflow, in a specific repository, and on a specific commit.

The tool generates a manifest according to the in-toto standard and SLSA (Supply-chain Levels for Software Artifacts) specification. Then the most interesting part happens: signing this manifest.

Instead of forcing developers to generate long-lived PGP keys and store them in repository secrets, Sigstore architecture is used. The action requests a temporary OIDC token from GitHub Actions and exchanges it for a short-lived signing certificate.

For public repositories, the signature is generated through the public Sigstore service, and data about it ends up in the transparent Rekor log. If the repository is private, GitHub uses its own private Sigstore instance (this feature is available on the Enterprise Cloud plan).

A small surprise in the documentation

If you open the project's official repository, you'll see an important note right at the beginning of the README.

Starting from version four, actions/attest-build-provenance turned into a simple wrapper over the base action actions/attest. The GitHub developers explicitly state: if you're maintaining old pipelines, you can leave everything as is. But for new projects, you should start with actions/attest right away.

Why did GitHub add an extra layer? Initially, the team was building a narrowly specialized tool only for build provenance. Later, the desire emerged to sign not only binaries but also SBOMs (dependency lists) or vulnerability scan results. That's how the more universal actions/attest appeared, and the old action was retired as a synonym.

What the setup looked like

In older versions of the action, the logic in .github/workflows/build.yml was compressed to a couple of lines after the artifact build step.

What's important here are the permissions id-token: write and attestations: write. Without the first option, the workflow won't be able to get an OIDC token for passwordless signing via Sigstore, and without the second, it won't upload the result to the GitHub Attestations API.

How to verify artifact authenticity

After the attestation is created and bound to the repository, any user or verification script can check the file locally. For this, the official GitHub CLI utility is used.

The verification command looks like this:

gh attestation verify app.sh --owner my-organization

If the file hasn't changed and was built in the specified organization, the CLI will output information about the commit and signing certificate. However, if the file has been modified even minimally, the verification will fail with an error.

Is it worth implementing

If you're developing an open-source library or CLI tool, generating attestations gives users an easy way to verify the security of your releases.

On the other hand, if you have a small internal project without strict supply chain security requirements, adding extra steps to your CI may be overkill.

For new workflows, use actions/attest directly instead of actions/attest-build-provenance. The core functionality will remain the same, but you'll be using an up-to-date tool without deprecated wrappers.

Related projects