Skip to content
Ashish.
All posts
Diagram illustrating supply chain identity and keyless signing workflow.
6 min readSecurityPlatform Engineers, Security Engineers#supply chain security#slsa#provenance#build identity#keyless signing#software supply chain#verification

Supply Chain Identity: Signing Who Built What

Explore supply chain identity and keyless signing to verify build provenance and enforce verification policies for secure software delivery.

By Ashish Kumar

Modern software delivery faces a fundamental crisis of identity. We know what an artifact is (its hash), but we rarely know who built it with certainty. Traditional build processes rely on metadata—git commit hashes, build timestamps, and environment variables—that can be spoofed or manipulated. This ambiguity allows attackers to inject malicious code into legitimate pipelines, creating a "supply chain ambiguity" that undermines security.

The solution is Supply Chain Identity, which shifts trust from the artifact's content to the process that created it. By using keyless signing mechanisms, we can cryptographically prove that a specific build was produced by a trusted CI/CD pipeline under strict conditions. This enables strong verification policies that ensure only builds from verified sources are deployed.

The Problem of Ambiguous Identity

Consider a typical build pipeline. A developer pushes code to GitHub, triggering a GitHub Actions workflow. The workflow compiles the code, runs tests, and produces a binary. The binary is uploaded to a package registry with a SHA-256 hash.

The problem is that the hash alone does not prove origin. An attacker who compromises a developer's machine could:

  1. Clone the repository.
  2. Inject malicious code.
  3. Generate the same git commit hash (by rebasing or manipulating history) or simply reuse a previously signed artifact's hash.
  4. Upload the malicious binary to the registry.

From the perspective of a downstream consumer (like a package manager or a deployment system), the malicious binary looks identical to the legitimate one because it has the same hash. The metadata (e.g., "built by GitHub Actions") is stored in a separate provenance file, which can also be spoofed if the signing key is compromised or if the provenance generation logic is flawed.

This is known as the supply chain ambiguity problem: the artifact's identity is decoupled from its provenance. Without a mechanism to bind the artifact to the specific build process, we cannot enforce supply chain security effectively.

Common Pitfalls

Implementing supply chain identity introduces new complexities. Common mistakes include:

  • Trusting Metadata Without Verification: Assuming that CI/CD logs or environment variables are sufficient proof of origin. These are easily spoofed by attackers with access to the build environment.
  • Key Leakage: Using long-lived private keys instead of ephemeral ones. If a private key is stolen, an attacker can sign malicious artifacts indefinitely.
  • Overly Broad Policies: Defining verification policies that are too loose (e.g., allowing any branch), which negates the security benefits of identity binding.

Mechanism of Keyless Signing

A schematic sequence diagram showing the keyless signing process : Step 1 OIDC token request, Step 2 Fulcio certificate issuance, Step 3 Artifact signing with ephemeral key, Step 4 Provenance attachment, rendered in flat technical style.

Keyless signing solves this by leveraging OpenID Connect (OIDC) tokens issued by CI/CD providers. Instead of storing a long-lived private key (which can be stolen), the build process obtains a short-lived, cryptographically signed OIDC token from the CI/CD provider (e.g., GitHub, GitLab, Azure DevOps).

Here’s how it works in practice:

  1. OIDC Token Request: The build job requests an OIDC token from the CI/CD provider. This token contains claims about the build context: repository, branch, commit SHA, actor, and workflow ID.
  2. Signing with Fulcio: The build process uses a Fulcio certificate, issued by the Sigstore CA, to sign the artifact. The Fulcio certificate is bound to the OIDC token. The private key used for signing never leaves the ephemeral build environment; it is generated on-the-fly and discarded after use.
  3. Provenance Attachment: The build process generates a SLSA (Supply-chain Levels for Software Artifacts) provenance statement, which is also signed using the same ephemeral key. This provenance statement includes the full build configuration, source code references, and build arguments.

The result is an artifact signed with a key that is uniquely tied to the specific build event. Verification checks the certificate identity (derived from the OIDC claims embedded in the certificate) rather than verifying OIDC token claims directly. This distinguishes the token (proof of identity) from the certificate (binding identity to key). If an attacker tries to reuse a previous signature, the certificate identity will not match the expected build context, and the signature will fail verification.

Example: Signing with Sigstore

# 1. Obtain OIDC token from GitHub Actions
# The token is typically available via an environment variable or API endpoint
export TOKEN=$(curl -H "Authorization: Bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" "$ACTIONS_ID_TOKEN_REQUEST_URL")
 
# 2. Sign the artifact using cosign (Sigstore tool)
cosign sign-blob \
  --identity-token="$TOKEN" \
  --certificate-oidc-issuer="https://token.actions.githubusercontent.com" \
  --certificate-identity="repo:myorg/myrepo:ref:refs/heads/main" \
  --output-signature=artifact.sig \
  artifact.bin
 
# 3. Verify the signature
cosign verify-blob \
  --signature=artifact.sig \
  --certificate-oidc-issuer="https://token.actions.githubusercontent.com" \
  --certificate-identity="repo:myorg/myrepo:ref:refs/heads/main" \
  artifact.bin

In this example, the verification step checks not just the signature, but also the certificate identity. The --certificate-identity flag ensures that the signature is only valid if it was generated by a build running on the main branch of myorg/myrepo. If an attacker tries to sign a malicious artifact from a different branch or repository, the verification will fail.

Enforcing Verification Policies

A conceptual diagram of a verification policy gate in a Kubernetes cluster, showing a container image being scanned against rules like Source, Branch, and SLSA Level, with a green checkmark for valid and red X for invalid, rendered in isometric style.

The true power of supply chain identity lies in verification policies. These policies define the rules for accepting an artifact based on its provenance and signature.

A typical verification policy might look like this:

  • Source: The artifact must be signed by a build from github.com/myorg/myrepo.
  • Branch: The build must have been triggered on the main branch.
  • Provenance Level: The build must meet SLSA Level 3 (ensuring the build environment was isolated and the provenance is tamper-proof).
  • Time: The signature must be less than 24 hours old (to prevent reuse of old signatures).

These policies are enforced by downstream systems, such as package managers (e.g., npm, pip) or deployment platforms (e.g., Kubernetes, Helm). When an artifact is pulled, the system verifies the signature against the policy. If the policy fails, the artifact is rejected.

Policy Enforcement in Practice

Consider a Kubernetes cluster that uses Kyverno or OPA/Gatekeeper to enforce policies. The admission controller can check the signature of a container image before allowing it to be deployed:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: verify-slsa-provenance
spec:
  validationFailureAction: Enforce
  rules:
  - name: verify-image
    match:
      any:
      - resources:
          kinds:
          - Pod
    verifyImages:
    - imageReferences:
      - "*.docker.io/myorg/myapp:*"
      attestors:
      - entries:
        - keyless:
            issuer: "https://token.actions.githubusercontent.com"
            subject: "repo:myorg/myrepo:ref:refs/heads/main"
      attestations:
      - predicateType: https://slsa.dev/provenance/v0.2

This policy ensures that only images built from the main branch of myorg/myrepo using GitHub Actions are allowed to run in the cluster. Any attempt to deploy an image from a different source, or a forked repository, will be blocked.

Practical Takeaways

  • Bind Identity to Process: Use keyless signing to cryptographically link artifacts to their specific build environments.
  • Enforce Strict Policies: Define verification policies that check source, branch, and provenance level to prevent unauthorized deployments.
  • Automate Verification: Integrate verification checks into CI/CD pipelines and deployment gateways to ensure compliance.
  • Monitor and Audit: Regularly audit signing certificates and policy enforcement to detect anomalies.

FAQ

Q: What happens if my CI/CD provider's OIDC issuer changes? A: You will need to update the --certificate-oidc-issuer in your verification tools and policies. Sigstore supports multiple issuers, so you may need to configure your tools to accept the new issuer.

Q: Can I use keyless signing with private repositories? A: Yes, most major CI/CD providers (GitHub, GitLab, Azure DevOps) support OIDC tokens for private repositories. Ensure your workflow permissions are correctly configured to allow token generation.

Q: How do I handle key rotation or certificate expiration? A: Since keyless signing uses ephemeral keys and short-lived certificates, there is no long-term key to rotate. Certificates expire automatically (usually within about ten minutes), so you simply need to ensure your verification tools are configured to accept certificates issued by the correct issuer.

Conclusion

Supply chain identity transforms security from a reactive, hash-based model to a proactive, process-based model. By using keyless signing and OIDC tokens, we can cryptographically bind artifacts to their build processes, eliminating ambiguity and enabling strict verification policies.

This approach does not eliminate the need for secure coding practices or vulnerability scanning, but it adds a critical layer of trust: provenance. It ensures that we know exactly where our software came from, who built it, and how it was built. In an era of sophisticated supply chain attacks, this level of transparency is not just beneficial—it is essential.

The shift to supply chain identity requires changes in tooling and processes, but the benefits are clear: reduced risk of supply chain compromise, automated enforcement of security policies, and greater confidence in the software we deploy. As the ecosystem matures, tools like Sigstore, SLSA, and various CI/CD integrations will make it easier than ever to implement these practices.

Related posts