Cosign image verification
When your customers pull container images from your registries, they want proof the binary came from a trusted build pipeline and nothing has tampered with it since. Cosign (Sigstore) does that with keyless signing — no long-lived signing keys, no key management drama.
fremforge ships a workflow template (cosign-verify-images.yaml) that walks your repo, finds every digest-pinned image reference, runs cosign verify against it, and reports the result back to fremforge. Results land on /<org>/_admin/code-security/images under a new Cosign column.
Why keyless signing
Traditional code signing requires you to manage a private key — store it in HSMs, rotate it, revoke it when leaked. Cosign keyless takes the OIDC token your CI already has, asks Fulcio (Sigstore’s CA) for a short-lived certificate bound to that identity, and records the signing event in Rekor (Sigstore’s transparency log). Total key custody: zero. Audit trail: full.
For a fremforge customer, this means:
- Your CI signs container images with whatever OIDC identity it’s running as (the
FREMFORGE_API_TOKENis not the signing identity). - Verifiers (you, your downstream customer, fremforge) can cryptographically confirm the image came from that identity at that time.
- Revocation is irrelevant: the cert was only valid for the few seconds it took to sign.
Workflow template
Install via Org admin → Code security → Container images → Install Cosign workflow, or drop the template at .forgejo/workflows/cosign-verify-images.yaml and let fremforge substitute the placeholders.
The template:
- Greps every digest-pinned image reference out of your Helm values, Kubernetes manifests, and docker-compose files.
- Runs
cosign verifyagainst each with permissive identity regexes (any signed image passes). - POSTs verification results to
https://frem.sh/_app/api/v1/cosign/verificationsas NDJSON.
You can tighten the identity matching to require signatures from specific OIDC issuers — see the next section.
Per-org enforcement
The tenant_security_policies table carries two new columns:
require_signed_images: bool— whentrue, any unsigned image referenced in your repos raises a finding on/<org>/_admin/code-security/images.require_signed_images_issuer_allowlist: text[]— empty means accept any Fulcio-issued signature; populated means only signatures whose OIDC issuer matches one of the listed entries pass.
Use the allowlist when you want to constrain signers to your own SSO (e.g. https://idp.fremverk.com) rather than accepting any keyless signature.
What “signed” actually means here
A signed image carries an OCI signature object alongside the image manifest in the registry. Cosign creates it, Rekor logs it, the verifier checks both. fremforge stores three things per (tenant, image):
signed(bool)signer_subject(the OIDC subject — usually a GitHub Actions / Forgejo workload identity)signer_issuer(the IdP that vouched for it)
For an unsigned image, fremforge stores signed=false and a free-text verification_details capturing why cosign rejected.
See also
- SBOMs — the what’s in this image side.
- Image scanning — the what’s vulnerable in this image side.