Explanation

Trust Levels

Progressive trust model: start with integrity, add signatures when ready, enforce identity constraints.

Overview

The epack verify command supports a progressive trust model. You don't need to adopt everything at once. Start with basic integrity checks and add more verification flags as your trust requirements grow.

This approach recognizes that different contexts have different needs. Internal packs from trusted sources may only need integrity verification. Packs from external vendors should have signatures with specific identity constraints.

Quick Reference
# Level 1: Integrity only
epack verify --integrity-only evidence.pack

# Level 2: Require any valid signature
epack verify --require-attestation evidence.pack

# Level 3: Require specific signer identity
epack verify --issuer "https://accounts.google.com" --subject "security@vendor.com" evidence.pack

The Three Levels

Level 1

Unsigned (Integrity)

SHA-256 digests verify file integrity. Detect tampering but not provenance.

$ epack verify --integrity-only evidence.pack

 Pack integrity verified
  Pack digest: sha256:a3f2b8c9d4e5f6...
  Artifacts: 12 verified
  No attestations present

What it proves

  • No files have been modified since the pack was created
  • No files have been added or removed
  • The manifest accurately describes the pack contents

What it doesn't prove

  • Who created the pack
  • When the pack was created
  • Whether the pack came from a trusted source
Level 2

Signed (Provenance)

Sigstore signatures prove who created the pack. Keyless via OIDC identity.

$ epack verify --require-attestation evidence.pack

 Pack verified with attestation
  Pack digest: sha256:a3f2b8c9d4e5f6...
  Signer: someone@example.com
  Issuer: https://accounts.google.com
  Signed: 2024-02-15T10:30:00Z

What it proves

  • Everything from Level 1
  • A valid Sigstore signature exists
  • The signature is recorded in the transparency log
  • The pack contents haven't changed since signing
Warning: Without identity constraints, any valid Sigstore user can sign. This level is insufficient for external packs.
Level 3

Verified (Policy)

Enforce specific signer identities. Only accept packs from trusted sources.

$ epack verify evidence.pack \
    --issuer "https://accounts.google.com" \
    --subject "security@vendor.com"

 Pack verified with policy
  Pack digest: sha256:a3f2b8c9d4e5f6...
  Signer: security@vendor.com ✓ matches
  Issuer: https://accounts.google.com ✓ matches
  Signed: 2024-02-15T10:30:00Z

What it proves

  • Everything from Level 2
  • The signer authenticated via the expected OIDC provider
  • The signer's identity matches your constraints
  • The pack came from a specific, trusted source
Recommended: Always use Level 3 for packs from external vendors.

Choosing a Level

Context Recommended Level Rationale
Internal packs from trusted CI/CD Level 1 Trust the pipeline; verify integrity only
Packs from internal teams Level 2 Require signature, but any internal user is acceptable
Packs from external vendors Level 3 Require signature from specific vendor identity
Packs from CI/CD with OIDC Level 3 Verify the exact workflow that produced the pack
Air-gapped or offline Level 1 Signature verification requires network access

Identity Patterns

Level 3 verification supports several identity matching patterns:

Exact email match

# Accept only packs signed by a specific email
epack verify evidence.pack \
  --issuer "https://accounts.google.com" \
  --subject "security@vendor.com"

GitHub Actions workflow

# Accept packs signed by any workflow in a specific repo
epack verify evidence.pack \
  --issuer "https://token.actions.githubusercontent.com" \
  --subject-regexp "https://github.com/vendor/repo/.*"

# Accept only packs from a specific workflow file
epack verify evidence.pack \
  --issuer "https://token.actions.githubusercontent.com" \
  --subject "https://github.com/vendor/repo/.github/workflows/release.yml@refs/heads/main"

Organization domain

# Accept any user from a specific domain
epack verify evidence.pack \
  --issuer "https://accounts.google.com" \
  --subject-regexp ".*@vendor\\.com$"

Failed verification

When verification fails, the error message explains what didn't match:

$ epack verify evidence.pack \
    --issuer "https://accounts.google.com" \
    --subject "security@vendor.com"

 Verification failed: signer identity mismatch
  Expected subject: security@vendor.com
  Actual subject:   other@example.com

Transitioning Between Levels

Organizations often start at Level 1 and progress as their processes mature:

  1. Start with Level 1: Get comfortable with the format. Build packs with epack build, verify integrity with epack verify --integrity-only, and use epack diff to compare releases.
  2. Add signatures (Level 2): Set up Sigstore signing with epack sign. Start requiring signatures with --require-attestation.
  3. Enforce identity (Level 3): Define which identities are acceptable for each vendor. Add --issuer and --subject flags to your verification commands.
Example: CI/CD verification script
#!/bin/bash
# Verify vendor pack with Level 3 policy

epack verify "$1" \
  --issuer "https://accounts.google.com" \
  --subject "security@vendor.com" \
  || exit 1

echo "Pack verified, extracting..."
epack extract "$1" --output ./evidence/

See Also