Artifact Tampering Risk
Build artifacts (binaries, container images, packages) produced without cryptographic signatures or provenance attestations can be silently replaced by an attacker between the CI build and deployment, resulting in supply chain compromise.
How It Works
In a CI/CD pipeline, code is built into artifacts: Docker images, npm packages, compiled binaries, or deployment bundles. These artifacts are typically pushed to a registry or artifact store. If the artifacts are not cryptographically signed, there is no way to verify they were produced by your legitimate CI pipeline and have not been modified. An attacker who gains access to the artifact registry (via leaked credentials, misconfigured permissions, or a compromised CI step) can replace a legitimate artifact with a malicious one. Without signature verification at deployment time, the tampered artifact is deployed to production. SLSA (Supply-chain Levels for Software Artifacts) and Sigstore provide frameworks for signing and verifying artifact provenance.
# BAD: Docker image built and pushed without signing or attestation
name: Build and Push
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/build-push-action@v5
with:
push: true
tags: ghcr.io/myorg/myapp:latest
# No signing, no attestation, no SBOM
# Anyone with registry write access can replace this image# GOOD: Docker image with cosign signature and SLSA provenance
name: Build and Push
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
id-token: write # needed for cosign keyless signing
steps:
- uses: actions/checkout@v4
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/build-push-action@v5
id: build
with:
push: true
tags: ghcr.io/myorg/myapp:${{ github.sha }}
- uses: sigstore/cosign-installer@v3
- run: cosign sign --yes ghcr.io/myorg/myapp@${{ steps.build.outputs.digest }}Real-World Example
The 2020 SolarWinds attack is the most notorious example of artifact tampering. Attackers compromised SolarWinds' build system and injected malicious code into the Orion software build process. The tampered build artifacts were signed with SolarWinds' legitimate code-signing certificate and distributed to 18,000 customers including US government agencies. Had artifact provenance attestation been in place, the unauthorized modification of the build output could have been detected.
How to Prevent It
- Sign all build artifacts using cosign (Sigstore) for container images or GPG for packages and binaries
- Generate SLSA provenance attestations in CI to cryptographically prove which source code, builder, and build steps produced each artifact
- Use immutable tags (commit SHA or digest) instead of mutable tags like 'latest' to prevent tag-based replacement attacks
- Verify artifact signatures at deployment time before pulling or running any artifact in production environments
Affected Technologies
Data Hogo detects this vulnerability automatically.
Scan Your Repo FreeRelated Vulnerabilities
Unpinned GitHub Actions
highUsing GitHub Actions referenced by mutable tags like @main or @v3 instead of full commit SHAs means a compromised or hijacked action can inject malicious code into your CI pipeline without any change to your workflow file.
GitHub Actions Script Injection
criticalUsing untrusted event data like github.event.issue.title directly inside run: blocks allows attackers to inject arbitrary shell commands into your CI pipeline by crafting malicious issue titles, PR bodies, or commit messages.
Secrets Leaked in CI Logs
highPrinting or echoing environment variables containing secrets in CI scripts exposes them in build logs, which are often accessible to all repository collaborators and sometimes publicly visible on open-source projects.
Self-Hosted Runner Risks
highUsing self-hosted GitHub Actions runners with pull_request_target or public fork workflows allows untrusted code from external contributors to execute on your infrastructure with access to secrets, persisted state, and the host network.