Docs/Security/Signing & Provenance

Signing & Provenance

DepAegis integrates Sigstore keyless signing and SLSA provenance to provide cryptographic proof that packages were built by trusted CI pipelines and have not been tampered with.

Why Signing Matters

Without signing, there is no way to verify that a package was actually published by the expected author. An attacker with access to the registry could replace a package with a malicious version, and consumers would have no way to detect the tampering.

Package signing provides:

When combined with provenance, signing also proves howthe package was built — which CI pipeline, from which source commit, with what build configuration. This creates a verifiable chain of trust from source code to published artifact.

Sigstore Integration (Keyless Signing)

DepAegis uses Sigstore for keyless signing. Keyless signing eliminates the need to manage private keys. Instead, the signer authenticates with an identity provider (GitHub, Google, Microsoft) and receives a short-lived signing certificate from the Sigstore Fulcio certificate authority.

The signing flow:

  1. The publisher authenticates with DepAegis (via token or OIDC in CI).
  2. DepAegis requests a signing certificate from Fulcio, bound to the publisher’s identity.
  3. The package artifact is signed with the certificate.
  4. The signature and certificate are recorded in the Rekor transparency log.
  5. The signature is stored alongside the package in the registry.
Keyless signing means there are no private keys to leak, rotate, or manage. The identity binding is verifiable by anyone — consumers can check that a package was signed by a specific GitHub Actions workflow or a specific developer account.

Verifying a Sigstore signature

# Verify a package signature using cosign
cosign verify-blob \
  --certificate-identity=repo@myorg.iam.gserviceaccount.com \
  --certificate-oidc-issuer=https://token.actions.githubusercontent.com \
  --certificate=signature.pem \
  --signature=signature.sig \
  package.tgz

If verification succeeds, the artifact was signed by the specified identity and has not been modified since.

SLSA Provenance Levels

SLSA (Supply-chain Levels for Software Artifacts) is a security framework that defines a series of increasing levels of assurance for software supply chain integrity.

LevelDescriptionDepAegis Support
SLSA 1Documentation of the build process. The provenance describes how the package was built.Supported — automatically generated for all packages.
SLSA 2Hosted build platform. The provenance is signed by the build platform, not the developer.Supported — signed by DepAegis CI integration.
SLSA 3Hardened builds. The build platform secures the provenance against tampering by the builder.Supported — with GitHub Actions or GitLab CI integration.
SLSA 4Two-party review + hermetic builds. Maximum assurance.Partially supported — requires specific CI configuration.
Most organizations should target SLSA Level 2 as a baseline. It ensures that provenance is signed by the build platform, preventing a compromised developer machine from forging build attestations.

How DepAegis Generates Provenance

When a package is published through a CI/CD pipeline integrated with DepAegis, the following provenance is automatically generated:

  1. Source information — the Git repository URL, commit SHA, and ref (branch/tag).
  2. Build configuration — the CI workflow file path and trigger event.
  3. Builder identity — the CI platform and service account that ran the build.
  4. Artifact hash — the SHA-256 digest of the published package.
  5. Timestamp — when the build started and finished.

The provenance document follows the SLSA provenance v1 format (in-toto statement) and is signed using the Sigstore infrastructure.

{
  "_type": "https://in-toto.io/Statement/v1",
  "subject": [
    {
      "name": "@myorg/ui-components",
      "digest": { "sha256": "abc123..." }
    }
  ],
  "predicateType": "https://slsa.dev/provenance/v1",
  "predicate": {
    "buildDefinition": {
      "buildType": "https://github.com/actions/workflow",
      "externalParameters": {
        "repository": "https://github.com/myorg/ui-components",
        "ref": "refs/tags/v1.2.3",
        "workflow": ".github/workflows/publish.yml"
      },
      "resolvedDependencies": [
        {
          "uri": "https://github.com/myorg/ui-components",
          "digest": { "gitCommit": "def456..." }
        }
      ]
    },
    "runDetails": {
      "builder": {
        "id": "https://github.com/actions/runner"
      },
      "metadata": {
        "invocationId": "https://github.com/myorg/ui-components/actions/runs/12345",
        "startedOn": "2026-06-11T09:00:00Z",
        "finishedOn": "2026-06-11T09:02:30Z"
      }
    }
  }
}

Verifying Signatures

Consumers and automated systems can verify package signatures at any time:

Using the DepAegis API

# Get signature and provenance for a package version
curl -H "Authorization: Bearer $DEPAEGIS_TOKEN" \
  "https://app.depaegis.com/api/v1/packages/@myorg%2Fui-components/versions/1.2.3/signature"

# Response:
# {
#   "signed": true,
#   "signer": "repo@myorg.iam.gserviceaccount.com",
#   "issuer": "https://token.actions.githubusercontent.com",
#   "provenance_level": "SLSA_LEVEL_2",
#   "certificate_uri": "https://rekor.sigstore.dev/api/v1/log/entries/...",
#   "verified_at": "2026-06-11T09:02:31Z"
# }

Using the Dashboard

The DepAegis dashboard shows a Signing & Provenance badge on each package version:

Cosign Integration for Containers

For Docker/OCI images, DepAegis integrates with cosign for container signing and verification. Images pushed to the DepAegis OCI registry are automatically signed using Sigstore keyless signing.

# Verify a container image signature
cosign verify \
  --certificate-identity=repo@myorg.iam.gserviceaccount.com \
  --certificate-oidc-issuer=https://token.actions.githubusercontent.com \
  app.depaegis.com/myorg/api-server:v1.2.3

You can also sign images manually before pushing:

# Sign an image with cosign (keyless)
cosign sign --yes app.depaegis.com/myorg/api-server:v1.2.3

# Sign with a custom key
cosign sign --key cosign.key app.depaegis.com/myorg/api-server:v1.2.3
Enable the block unsigned packages firewall policy to ensure only signed images can be pulled from your registry. This prevents compromised build pipelines from injecting unverified images.

Package Signature Verification in npm

Starting with npm v9, the npm CLI can verify package signatures from the registry. When using DepAegis as your npm registry, signature verification is supported out of the box.

# npm automatically verifies signatures during install
npm install @myorg/ui-components

# If verification fails, npm will warn:
# npm WARN signature verification failed for @myorg/ui-components@1.2.3

To enforce signature verification strictly, use the --verify-signature flag:

npm install --verify-signature @myorg/ui-components

This causes npm to fail the install if the signature cannot be verified, rather than just warning.

Best Practices for Signing in CI/CD

To maximize the security benefits of signing and provenance, follow these best practices:

1. Use OIDC authentication in CI

Configure your CI pipeline to authenticate with DepAegis using OIDC (OpenID Connect) instead of long-lived tokens. This binds the signing identity to the specific CI job:

# GitHub Actions: publish with OIDC
- name: Publish to DepAegis
  uses: depaegis/publish-action@v2
  with:
    registry: app.depaegis.com
  id-token: write  # enables OIDC

2. Sign at build time, not publish time

The signature should cover the built artifact, not just the publish action. Sign the tarball or image as the final step of your build job, before it leaves the CI environment.

3. Include provenance metadata

Always generate provenance alongside the signature. The provenance provides context about how the artifact was built, which is essential for auditing and incident response.

4. Enforce signing in the firewall

Activate the block unsigned packages and block packages without provenance firewall policies. This ensures that no unsigned or unprovenanced package can enter your registry, even if a publisher forgets to sign.

5. Verify in your consumer pipeline

Add a signature verification step to your CI pipeline that runs npm audit signatures or cosign verify as part of your build process. This catches tampered dependencies before they reach production.

# GitHub Actions: verify all dependencies are signed
- name: Verify dependency signatures
  run: npm audit signatures --registry=https://app.depaegis.com
Signing adds value only if consumers verify. A signature that nobody checks provides no protection. Make verification a mandatory step in your build pipeline.