Introducing Artifact Attestations–now in public beta

Generate and verify signed attestations for anything you make with GitHub Actions.

|
| 8 minutes

June 25, 2024 update: Artifact Attestations is now generally available! Get started today.

There’s an increasing need across enterprises and the open source ecosystem to have a verifiable way to link software artifacts back to their source code and build instructions. And with more than 100M developers building on GitHub, we want to ensure developers have the tools needed to help protect the integrity of their software supply chain. Today, we’re proud to announce the public beta of Artifact Attestations, a new feature that will pave the way for a cultural shift toward expecting to know where software comes from.

Artifact Attestations allow project maintainers to effortlessly create a tamper-proof, unforgeable paper trail linking their software to the process which created it. Downstream consumers of that metadata can then use it as a foundation for new security and validity checks through policy evaluation via tools like Rego and Cue. We’re starting with verification support based on GitHub CLI, but will expand to bring these same controls to the Kubernetes ecosystem as well later this year.

Artifact Attestations is powered by Sigstore, an open source project for signing and verifying software artifacts. This means open source maintainers can reduce their project’s exposure to supply chain attacks and increase the security of the broader software ecosystem–no matter where maintainers host their code, or build their artifacts. Let’s jump in.

Flow chart demonstrating that if a customer Actions workflow is in a public repository, it can be attested with Public Good Sigstore, and stored in a public transparency log. If it is in a private repository, attestation happens with GitHub Sigstore, and the attestation is stored in a private transparency log.

An effortless user experience

Security features need to be more than just powerful—they have to be simple to adopt and easy to configure in order to be effective. Artifact Attestations couldn’t be easier to set up: all you need to do is add a bit of YAML to your GitHub Actions workflow to create an attestation and install the GitHub CLI tool to verify it.

  1. Enable your GitHub Actions workflow to write to the attestations store:
    permissions:
      id-token: write
      attestations: write
      contents: read
    
  2. Direct a workflow to create an attestation, making sure to place it after the artifact is generated:
        - name: Attest Build Provenance
            uses: actions/attest-build-provenance@897ed5eab6ed058a474202017ada7f40bfa52940 # v1.0.0
            with:
            subject-path: "bin/my-artifact.tar.gz"
    
  3. Once your build is finished and you have the artifact downloaded, use GitHub CLI (version 2.49.0 or greater) to verify it, providing the name of the organization that contains the repository where the action ran:
    gh attestation verify my-artifact.tar.gz -o my-organization
    

It’s also easy to download the attestation document itself for storage or offline verification (for example, in an air-gapped environment), quickly look at certificate details, or extract verified attestation contents in a JSON form so you can pipe it to a policy engine like OPA.

package attestation.slsa1
import future.keywords.if

approved_repos := [
    "https://github.com/sigstore/sigstore-js",
    "https://github.com/github/example",
]

# Fail closed
default allow := false

# Allow if the repository is in the approved_repos list and the predicateType matches
allow {
    some i
    # Check if the predicateType matches the required type
    input[i].verificationResult.statement.predicateType == "https://slsa.dev/provenance/v1"

    # Attempt to safely assign the repo variable
    repo := input[i].verificationResult.statement.predicate.buildDefinition.externalParameters.workflow.repository

    repo == approved_repos[_]
}

You can grab the attestation in JSON format and use the policy to verify myfile.zip came from an allowed repository in the policy like so:

$ gh attestation verify -R github/example --format json myfile.zip | \
opa eval  --stdin-input -f raw \
-d policy.rego "data.attestation.slsa1.allow == true"

true

Can I attest other things in my build, like SBOM?

If you have an SBOM that you’ve generated as part of your build, you can use the new attest-sbom action to associate it with a final artifact. You simply provide the path to that artifact and the action will take care of wrapping it in an in-toto attestation predicate, signing it with our internal Sigstore instance, and sending it to our attestation store. If you don’t already have an SBOM in your build and want a way to get started, the anchore/sbom-action offers support for container images and many language ecosystems.

To associate a build artifact with an attested SBOM, follow these steps:

  1. First (just like for provenance) you need to grant write permission for the attestation store to your workflow:
    permissions:
      id-token: write
      attestations: write
      contents: read
    
  2. Ensure that you actually have an SBOM that makes sense for your particular needs. Here’s an example of using Anchore’s Syft to scan a build directory:
    - uses: anchore/sbom-action@v0
      with:
        path: ./build/
        format: 'spdx-json'
        output-file: 'sbom.spdx.json'
    
  3. Finally, use the attest-sbom action to wrap the generated SBOM file contents in an in-toto SBOM predicate, sign it, associate it with your built artifact, and send it to the attestation store:
    - uses: actions/attest-sbom@v1
      with:
        subject-path: 'bin/my-artifact.tar.gz'
        sbom-path: 'sbom.spdx.json'
    

How it works

Artifact Attestations help reduce the complexity of deploying and managing public key infrastructure, instead placing trust in the security of your GitHub account. We accomplish this by signing a document with a temporary keypair. The public key is attached to a certificate associated with a build system’s workload identity, and the private key never leaves process memory and is discarded immediately after signing. This differs from other signing approaches that rely on human identities or long-lived keys. We believe that certificate revocation lists are too problematic to use effectively, and that the future of software provenance and signatures goes through workload identity. Here’s how:

  • When an attestation action executes, our Sigstore client requests the GitHub Actions OIDC token associated with that workflow run. It then creates a key pair and sends the public half to Fulcio, a certificate authority, along with the OIDC token. In the case of a public repository, Sigstore Public Good Instance’s Fulcio issues the cert. In the case of a private repository, the cert is issued by GitHub’s internal instance of Fulcio, ensuring that no customer information leaves GitHub.
  • When receiving the token, Fulcio validates the token’s signature and mints a new short-lived X.509 certificate binding the public key to the workflow’s OIDC identity.
  • Fulcio returns the certificate to the client running in GitHub Actions, which calculates a SHA-256 digest of the subject artifact, and writes out an in-toto statement which binds the subject to a predicate containing data from the OIDC token’s claims.
  • The client uses the private key to seal the in-toto statement in a DSSE signing envelope. Then, it throws the private key away. The envelope’s signature is sent to the TSA for a timestamp counter-signature, which proves that the signature was produced during the certificate’s 10-minute validity window.
  • Everything is wrapped up as a Sigstore bundle and persisted to GitHub’s attestation store. In the case of a private repository, that’s the end of the flow. In the case of a public repository, the attestation is additionally written to the Sigstore Public Good Instance and lands on Rekor, the project’s immutable ledger.

Artifact Attestations have been in an early access preview for the last several months, and we’re thrilled by the early feedback we’ve received.

GitHub is steadfast in its commitment to democratizing software attestations and artifact integrity. Leveraging just six lines of code in GitHub workflows marks a game-changer in build chain security—an initiative I've utilized, experienced, and enthusiastically embraced.

- Victor Martinez Rubio // Principal Engineer, Elastic

GitHub is now a root certificate authority

When we started designing the requirements for this feature, we realized quickly that we wanted users to be able to sign an artifact on GitHub Actions and then verify it anywhere, even offline. Public key infrastructure (PKI) is complex and high-stakes, and we heard from both customers and open source projects that they wanted a way to sign things without having to build out PKI or manage secrets which can be leaked or lost. To do this, we first needed to establish GitHub as a root certificate authority (CA) for signing software so that we could own the entire certificate chain.

In October 2023, we went live with an X.509 certificate authority and RFC 3161 timestamp server, with a trust root managed via a quorum of hardware tokens held by employees across a variety of geographies and roles. The trust root is managed with tooling from the TUF project (where we’re contributors), and the CA and timestamp services are instances of Sigstore applications. Intermediate certificates are housed in Azure KeyVault Managed HSMs, which are used to sign leaf certificates issued by Sigstore Fulcio and Sigstore Timestamp Authority. Signing certificates are valid for 10 minutes from the time of issuance, so there is no need to manage the complexities of Certificate Revocation Lists (CRLs).

Sigstore, in public and in private

In keeping with our commitment to offering cutting-edge features to both enterprise customers and the open source community, Artifact Attestations supports the same user experience offered in two basic modes depending on repository visibility. For public repositories, attestations generated on GitHub Actions will be written to the Sigstore Public Good Instance for verification in public on an immutable ledger. For private repositories on GitHub Enterprise plans, the attestations are written to an internal, completely private database and no information is written to public ledgers or logs.

A more secure future

It’s important to note that provenance by itself doesn’t make your artifact or your build process secure. What it does do is create a tamper-proof guarantee that the thing you’re executing is definitely the thing that you built, which can stop many attack vectors. It’s still vital to maintain strong application security processes like requiring code review for all patches, and applying dependency updates in a timely manner.

In other words: attestations provide you with a paper trail, which cannot be forged, tying a given artifact to a given GitHub Actions workflow run. We believe that this is a key piece of the modern trust model, and in addition we want to help effect a cultural shift toward folks knowing where their software components come from.

Artifact Attestations will allow customers unprecedented visibility into the composition and usage of their built software artifact, and this is just the beginning. We’ll be offering the ability to attest other kinds of artifacts associated with the build process, such as vulnerability reports and other pieces of metadata supported by the in-toto project’s defined predicate types. Look for exciting news around Kubernetes support, new guarantees for releases, and more later this year.

Want to learn more about how GitHub can take the stress out of shipping secure code?

At GitHub Universe 2024, we’ll explore cutting-edge research and best practices in developer-first security—so you can keep your code secure with tools you already know and love.

Our Super Early Bird sale ends soon! Buy your tickets now.

Related posts