sigstore-cosign

v2026.09.24

Sigstore — keyless signing for software artifacts using OIDC identities and short-lived certificates from Fulcio CA, with Rekor transparency log. Cosign is the CLI for signing/verifying containers, OCI artifacts, blobs, and attestations (SBOMs, provenance). Covers GitHub Actions OIDC integration, policy enforcement (cosign-policy-controller, Kyverno), Notary v2 vs Cosign, and supply-chain attestation patterns (SLSA). USE WHEN: user mentions "Sigstore", "Cosign", "Fulcio", "Rekor", "keyless signing", "OIDC signing", "cosign sign", "cosign verify", "SLSA provenance", "OCI artifact signing", "attestation cosign" DO NOT USE FOR: GPG-style signing - use GPG-specific docs DO NOT USE FOR: Code signing certificates (Apple Developer ID, Authenticode) - platform-specific DO NOT USE FOR: Reproducible builds spec - use `infrastructure/reproducible-builds`

GitHub
安装命令
npx skhub add claude-dev-suite/sigstore-cosign
Markdown
SKILL.md

Sigstore + Cosign — Keyless Artifact Signing

Deep Knowledge: Use mcp__documentation__fetch_docs with technology: sigstore or cosign.

Why Sigstore

Traditional signing requires long-lived private keys: distribute, secure, rotate, audit. Sigstore replaces the model with keyless signing:

  1. CI proves identity via OIDC (e.g., GitHub Actions has built-in OIDC token)
  2. Fulcio issues short-lived (10 min) X.509 cert bound to that identity
  3. Sign artifact, attach signature + cert to artifact
  4. Rekor transparency log records the signing event (Merkle tree)
  5. Verifier checks: cert chain is valid, identity matches expected, log entry exists

No keys to manage. Identity-based trust. Public auditability via Rekor.

Sigstore project includes:

  • Cosign — CLI for sign/verify (most-used component)
  • Fulcio — Code-signing CA
  • Rekor — Transparency log (https://search.sigstore.dev/)
  • Gitsign — Sign git commits with sigstore (replaces GPG)

Adopted by Kubernetes, npm (since 2023), GitHub container registry, JFrog, Wolfi/Chainguard images.

Install Cosign

# macOS
brew install cosign

# Linux
curl -LO https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-amd64
chmod +x cosign-linux-amd64 && sudo mv cosign-linux-amd64 /usr/local/bin/cosign

# Verify
cosign version

Sign a Container Image (Keyless)

# Push image first
docker push ghcr.io/bhodl/api:1.0.0

# Sign with keyless OIDC (browser opens for OAuth)
cosign sign ghcr.io/bhodl/api:1.0.0

# In CI (no interactive auth — uses ambient OIDC):
COSIGN_EXPERIMENTAL=1 cosign sign --yes ghcr.io/bhodl/api:1.0.0

The signature is stored as a separate OCI artifact next to the image (<image>:<digest>.sig).

Verify

cosign verify ghcr.io/bhodl/api:1.0.0 \
    --certificate-identity-regexp="^https://github\.com/bhodl/api/" \
    --certificate-oidc-issuer="https://token.actions.githubusercontent.com"

--certificate-identity-regexp constrains who could have signed (the workflow URL). --certificate-oidc-issuer constrains the OIDC provider.

For a specific workflow:

cosign verify ghcr.io/bhodl/api:1.0.0 \
    --certificate-identity="https://github.com/bhodl/api/.github/workflows/release.yml@refs/heads/main" \
    --certificate-oidc-issuer="https://token.actions.githubusercontent.com"

Sign with a Key (Traditional)

If you must use a key (e.g., air-gapped CI):

# Generate keypair (encrypted private key)
cosign generate-key-pair
# → cosign.key, cosign.pub

# Sign
cosign sign --key cosign.key ghcr.io/bhodl/api:1.0.0

# Verify
cosign verify --key cosign.pub ghcr.io/bhodl/api:1.0.0

For HSM/KMS-backed keys:

cosign sign --key azurekms://my-vault.vault.azure.net/my-key ghcr.io/bhodl/api:1.0.0
cosign sign --key gcpkms://projects/PROJ/locations/LOC/keyRings/RING/cryptoKeys/KEY ...
cosign sign --key awskms://us-east-1/KEY-UUID ...
cosign sign --key hashivault://my-key ...

Sign Blobs (Files, Not Containers)

# Sign a binary
cosign sign-blob --yes my-app.tar.gz \
    --output-signature my-app.tar.gz.sig \
    --output-certificate my-app.tar.gz.pem

# Verify
cosign verify-blob my-app.tar.gz \
    --signature my-app.tar.gz.sig \
    --certificate my-app.tar.gz.pem \
    --certificate-identity-regexp="^https://github\.com/bhodl/" \
    --certificate-oidc-issuer="https://token.actions.githubusercontent.com"

For a release: sign the SHA-256 of the artifact:

cosign sign-blob --yes <(sha256sum my-app.tar.gz | cut -d' ' -f1)

Attestations (Verifiable Metadata)

Attach SBOM, provenance, or custom predicates to an artifact:

# Generate SBOM (e.g., with syft)
syft ghcr.io/bhodl/api:1.0.0 -o spdx-json > sbom.spdx.json

# Attach as attestation
cosign attest --yes \
    --predicate sbom.spdx.json \
    --type spdxjson \
    ghcr.io/bhodl/api:1.0.0

# Verify attestation
cosign verify-attestation \
    --type spdxjson \
    --certificate-identity-regexp="^https://github\.com/bhodl/" \
    --certificate-oidc-issuer="https://token.actions.githubusercontent.com" \
    ghcr.io/bhodl/api:1.0.0

Predicate types:

  • slsaprovenance — build provenance (SLSA spec)
  • spdxjson, cyclonedx — SBOM formats
  • vuln — vulnerability scan
  • custom — your own JSON schema

SLSA Provenance

SLSA (Supply-chain Levels for Software Artifacts) — framework for build attestation. Generate provenance via SLSA GitHub action:

# .github/workflows/release.yml
permissions:
  id-token: write
  contents: read
  packages: write

jobs:
  build:
    runs-on: ubuntu-latest
    outputs:
      digest: ${{ steps.build.outputs.digest }}
    steps:
      - uses: actions/checkout@v4
      - id: build
        run: |
          docker buildx build --push --tag ghcr.io/bhodl/api:${{ github.sha }} . > digest.txt
          echo "digest=$(cat digest.txt)" >> $GITHUB_OUTPUT

  provenance:
    needs: build
    permissions:
      actions: read
      id-token: write
      packages: write
    uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.0.0
    with:
      image: ghcr.io/bhodl/api
      digest: ${{ needs.build.outputs.digest }}
      registry-username: ${{ github.actor }}
    secrets:
      registry-password: ${{ secrets.GITHUB_TOKEN }}

Attestation auto-pushed alongside image, signed by Sigstore.

GitHub Actions OIDC Setup

Cosign keyless requires GitHub's id-token permission:

permissions:
  id-token: write          # required for OIDC
  contents: read
  packages: write          # if pushing to ghcr.io

jobs:
  sign:
    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 }}

      - name: Build & push
        run: |
          docker build -t ghcr.io/bhodl/api:${{ github.sha }} .
          docker push ghcr.io/bhodl/api:${{ github.sha }}

      - name: Install cosign
        uses: sigstore/cosign-installer@v3.7.0

      - name: Sign image
        env:
          COSIGN_EXPERIMENTAL: "true"
        run: cosign sign --yes ghcr.io/bhodl/api:${{ github.sha }}

Policy Enforcement (Kubernetes)

Cosigned (deprecated) → policy-controller

helm install policy-controller \
    sigstore/policy-controller \
    --version 0.10.0 \
    -n cosign-system --create-namespace

Define policy:

apiVersion: policy.sigstore.dev/v1beta1
kind: ClusterImagePolicy
metadata:
  name: bhodl-images-must-be-signed
spec:
  images:
    - glob: ghcr.io/bhodl/**
  authorities:
    - keyless:
        url: https://fulcio.sigstore.dev
        identities:
          - issuer: https://token.actions.githubusercontent.com
            subjectRegExp: ^https://github\.com/bhodl/api/\.github/workflows/release\.yml@refs/heads/main$

Pods using ghcr.io/bhodl/* images that aren't signed by the right workflow → rejected.

Kyverno Equivalent

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: verify-signatures
spec:
  validationFailureAction: Enforce
  rules:
    - name: check-image-signatures
      match:
        any:
        - resources:
            kinds: [Pod]
      verifyImages:
        - imageReferences:
            - "ghcr.io/bhodl/*"
          attestors:
            - entries:
                - keyless:
                    subject: "https://github.com/bhodl/*"
                    issuer: "https://token.actions.githubusercontent.com"

Sign Git Commits — Gitsign

Sigstore replacement for GPG commit signing.

brew install gitsign

git config --global commit.gpgsign true
git config --global tag.gpgsign true
git config --global gpg.x509.program gitsign
git config --global gpg.format x509

# Sign a commit (browser opens for OAuth)
git commit -m "feat: add wallet sync"

# View signature
git log --show-signature -1

Inspect Sigstore Records

# Search Rekor for transparency log entries
rekor-cli search --email user@example.com
rekor-cli search --artifact my-app.tar.gz
rekor-cli get --uuid 24296fb24b8ad77a...

# Search via web UI
open https://search.sigstore.dev

Cosign vs Notary v2

FeatureCosign (Sigstore)Notary v2
Backed byOpenSSFCNCF
Standard for OCI signatureYes (de facto)Yes (formal)
Keyless (OIDC)✅ NativePlugin
Transparency log✅ RekorOptional
AdoptionWider (npm, GitHub, k8s)Growing (registry vendors)
Key-based fallback✅✅
Attestations✅ in-toto, SBOMs✅

For most users: Cosign. For enterprise registries (JFrog Artifactory, Harbor) that prefer Notary v2 spec: both supported, often interoperable.

Mobile App Signing (BHODL-style)

For wallet apps shipping APKs/IPAs/binaries publicly:

# .github/workflows/release.yml
jobs:
  release:
    runs-on: macos-14
    permissions:
      id-token: write
      contents: write
    steps:
      - uses: actions/checkout@v4
      - name: Build APK
        run: ./gradlew :apps:android:bundleRelease

      - name: Build XCFramework
        run: ./gradlew :shared:assembleSharedXCFramework

      - uses: sigstore/cosign-installer@v3.7.0

      - name: Sign artifacts
        run: |
          cosign sign-blob --yes apps/android/app/build/outputs/bundle/release/app-release.aab \
              --output-signature app-release.aab.sig \
              --output-certificate app-release.aab.pem

          cosign sign-blob --yes Bhodl.xcframework.zip \
              --output-signature Bhodl.xcframework.zip.sig \
              --output-certificate Bhodl.xcframework.zip.pem

      - name: Create GitHub Release
        uses: softprops/action-gh-release@v2
        with:
          files: |
            apps/android/app/build/outputs/bundle/release/app-release.aab
            app-release.aab.sig
            app-release.aab.pem
            Bhodl.xcframework.zip
            Bhodl.xcframework.zip.sig
            Bhodl.xcframework.zip.pem

Users verify before installing:

cosign verify-blob app-release.aab \
    --signature app-release.aab.sig \
    --certificate app-release.aab.pem \
    --certificate-identity="https://github.com/bhodl/wallet/.github/workflows/release.yml@refs/tags/v1.0.0" \
    --certificate-oidc-issuer="https://token.actions.githubusercontent.com"

Pair with reproducible builds (see infrastructure/reproducible-builds) for full chain: code → reproducible build → signed → verifiable.

Anti-Patterns

Anti-patternWhy it's badCorrect approach
Sharing private signing key in CI secretsSingle point of compromiseUse keyless OIDC
Skipping --certificate-identity-regexp on verifyAny signer acceptedAlways pin identity
Signing on dev workflowsPollutes Rekor with non-release signsSign only on tag/release workflows
Storing cosign.key in repoEven encrypted, exposes ciphertextUse HSM/KMS or keyless
cosign verify without --certificate-oidc-issuerAccepts any issuerPin issuer
Bundling signatures inside the artifactCan't verify externallyDistribute alongside (.sig, .pem)
No attestation for build provenanceCan't trace artifact → sourceUse SLSA provenance
Signing only the latest tag, not each releaseOld releases unverifiableSign every release
Ignoring Rekor inclusion proof during verifyCould miss tamperingcosign verify checks by default
Trusting latest tagMutableSign + verify by digest

Troubleshooting

SymptomCauseFix
Error: getting signer: getting key from KMS provider: getting OIDC tokenMissing OIDC permissionAdd id-token: write to workflow
verifying signature: no matching signaturesWrong certificate-identity-regexpLoosen regex or check actual identity in Rekor
cosign sign opens browser locally but failsBehind firewall, no OAuth callbackUse --identity-token flag with pre-fetched token
Signature pushed but cosign verify failsImage moved/retaggedVerify by digest, not tag
unsupported predicate typeCustom predicate, no built-in typeUse --type custom and provide schema
Slow verify in CINetwork round trip to RekorCache Rekor public key, use --rekor-url to point to mirror if needed
policy-controller denies known-good imageIdentity regex too strictTest with cosign verify first, match regex
Error reading signing keyEncrypted key + missing passwordCOSIGN_PASSWORD env or --password-file
Build artifact hash mismatch on verifyArtifact modified after signingRe-sign; ensure no post-build mutation

When NOT to Use This Skill

ScenarioUse Instead
Apple Developer ID code signingmobile/ios-native (build & distribution)
Android APK signing for Play StoreAndroid Gradle signing (signingConfigs)
Authenticode (Windows EXE/MSI)Windows-specific signing tooling
GPG-style signing for legacy systemsGPG docs
Reproducible builds specinfrastructure/reproducible-builds
发现
标签

此技能尚未发布标签。

版本
最新版本元数据

版本

v2026.09.24

发布时间

2026年9月24日

分类

未分类

许可证

MIT

源路径

skills/security/sigstore-cosign

默认分支

main

最新提交

9496306

Tree SHA

fe4e2f1