Image Verification
Verify sockguard images and release tarballs with cosign keyless GitHub Actions OIDC signatures.
Every sockguard release is signed with cosign using GitHub Actions OIDC keyless signing. Before running a sockguard image in production, verify it against the expected signing identity — this is the only reliable way to be sure you're running a binary we actually published.
What cosign verifies
The cosign verify command below verifies the image signature:
- The image digest was signed by a workflow whose OIDC identity matches the release pipeline in this repo.
- The signature is present in Sigstore transparency metadata.
- The certificate chains to the expected GitHub Actions OIDC issuer.
The release pipeline also requests SBOM output during image build and
publishes GitHub build-provenance attestations when repository visibility
supports them. Treat those as separate supply-chain artifacts: validate
the image or release tarball signature first, then inspect SBOM/provenance
with your registry or GitHub attestation tooling when you need that extra
evidence. A successful cosign verify alone does not prove SBOM or
provenance contents.
The signing identity is the full GitHub Actions workflow reference:
- Certificate identity pattern:
^https://github.com/CodesWhat/sockguard/.github/workflows/release-from-tag.yml@refs/tags/.+$ - OIDC issuer:
https://token.actions.githubusercontent.com
If either value differs from what cosign finds in the signature, the image was not produced by our release pipeline — do not run it.
Prerequisites
Install cosign (v2 or later is required for keyless verification):
# macOS
brew install cosign
# Linux (pre-built binary, pin the sha as you see fit)
curl -Lo cosign https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-amd64
chmod +x cosign
sudo mv cosign /usr/local/bin/One-liner verify
Replace <TAG> with the release tag you're pulling (for example
1.3.0 or latest):
cosign verify \
--certificate-identity-regexp '^https://github.com/CodesWhat/sockguard/.github/workflows/release-from-tag.yml@refs/tags/.+$' \
--certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
ghcr.io/codeswhat/sockguard:<TAG>A successful verification looks like:
Verification for ghcr.io/codeswhat/sockguard:<TAG> --
The following checks were performed on each of these signatures:
- The cosign claims were validated
- Existence of the claims in the transparency log was verified offline
- The code-signing certificate was verified using trusted certificate authority certificates
[{...}]The last line is a JSON object with the signing certificate details; any well-formed JSON there is proof the signature matched. If cosign returns a non-zero exit code, the signature is missing or does not match the expected identity.
Pinning by digest
For reproducible deployments, prefer verifying and pulling by SHA256 digest rather than by tag — a tag can be re-pointed, a digest cannot.
# Resolve the current digest for a tag
digest=$(docker buildx imagetools inspect \
ghcr.io/codeswhat/sockguard:<TAG> --format '{{json .Manifest.Digest}}' \
| tr -d '"')
# Verify against the digest
cosign verify \
--certificate-identity-regexp '^https://github.com/CodesWhat/sockguard/.github/workflows/release-from-tag.yml@refs/tags/.+$' \
--certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
"ghcr.io/codeswhat/sockguard@${digest}"
# Then reference the same digest in your compose file
# image: ghcr.io/codeswhat/sockguard@sha256:...If verification fails
Do not run the image. Treat a verification failure as a potential supply-chain compromise until proven otherwise:
- Double-check you pasted the full
certificate-identity-regexpand that the escaping survived your shell (^,$, and.+must all appear in the regex). - Run
cosign versionand confirm you have cosign v2 or later. - Try the verification again with a fresh registry pull; a stale cached manifest can sometimes produce confusing errors.
- If the identity or issuer values differ from the ones published
here, stop — open a private security advisory via the process in
SECURITY.mdso we can investigate.
Verifying release tarballs
The GitHub release assets (sockguard-v<TAG>.tar.gz) are also
cosign-signed. The release workflow uploads a sigstore bundle
(.sigstore.json) alongside each tarball:
cosign verify-blob \
--bundle "sockguard-v<TAG>.tar.gz.sigstore.json" \
--certificate-identity-regexp '^https://github.com/CodesWhat/sockguard/.github/workflows/release-from-tag.yml@refs/tags/.+$' \
--certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
"sockguard-v<TAG>.tar.gz"Same interpretation as the image verify: a clean exit code is a passing signature, anything else means stop and investigate.
Sockguard v2 and later publish only the sigstore bundle above. Published
releases in the v1.7 line also carry a legacy detached signature
(.sig) and signing certificate (.pem), so tooling scripted against the
older cosign verify-blob --signature --certificate invocation keeps
working. v1.7.2 has no GitHub release or release assets because its publish
workflow failed.
cosign verify-blob \
--certificate "sockguard-v<TAG>.tar.gz.pem" \
--signature "sockguard-v<TAG>.tar.gz.sig" \
--certificate-identity-regexp '^https://github.com/CodesWhat/sockguard/.github/workflows/release-from-tag.yml@refs/tags/.+$' \
--certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
"sockguard-v<TAG>.tar.gz"Cosign's own sign-blob deprecated those output flags in favor of the
bundle format. Use --bundle for current releases.
When release provenance is published, the release also includes
sockguard-v<TAG>.tar.gz.intoto.jsonl. Verify that attestation separately
from the tarball's cosign bundle before relying on it for SLSA evidence.
Verifying the per-platform binary archives
sockguard-v<TAG>.tar.gz above is the source snapshot. The archives
you download to actually run sockguard are the per-platform ones,
sockguard_<VERSION>_<OS>_<ARCH>.tar.gz (note the underscores and the
missing v). They're easy to confuse, so check which file you have
before picking a command.
Each per-platform archive ships its own .sigstore.json bundle, and so
does checksums.txt. Verify a single archive directly:
cosign verify-blob \
--bundle "sockguard_<VERSION>_linux_amd64.tar.gz.sigstore.json" \
--certificate-identity-regexp '^https://github.com/CodesWhat/sockguard/.github/workflows/release-from-tag.yml@refs/tags/.+$' \
--certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
"sockguard_<VERSION>_linux_amd64.tar.gz"Or verify checksums.txt once and check any archive against it, which is
the cheaper route when you're pulling several platforms:
cosign verify-blob \
--bundle "checksums.txt.sigstore.json" \
--certificate-identity-regexp '^https://github.com/CodesWhat/sockguard/.github/workflows/release-from-tag.yml@refs/tags/.+$' \
--certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
"checksums.txt"
sha256sum --check --ignore-missing checksums.txtSockguard v2 and later publish only .sigstore.json bundles. v1.7.5
dual-published those bundles with the legacy .sig/.pem pair for the
source tarball, checksums, and binary archives. v1.7.3-v1.7.4 published
only the legacy pair for checksums and binary archives; v1.7.0-v1.7.1 did
not sign those binary artifacts. v1.7.2 has no GitHub release or release
assets because its publish workflow failed. Use the assets actually attached
to the historical release rather than assuming every v1.7 tag has the same
set.
The archives also carry GitHub build-provenance attestations, which record the workflow and commit that produced them:
gh attestation verify "sockguard_<VERSION>_linux_amd64.tar.gz" \
--repo CodesWhat/sockguardEach archive additionally ships a CycloneDX SBOM as
sockguard_<VERSION>_<OS>_<ARCH>.tar.gz.cyclonedx.json.
Signatures and provenance on the per-platform archives start with the
first release cut after this change. Earlier releases have the SBOM only,
so a missing .sigstore.json on an older tag is expected rather than a
red flag.