Image signing and verification
Every container image pushed to your organization’s private registry by someone who is allowed to push is signed by Sencai with a key that belongs to your organization alone. The signature covers the image’s digest - the fingerprint of its exact content - so you can check, later and on any machine, that the image a server is running is the one your organization pushed and Sencai signed.
What a signature tells you
Section titled “What a signature tells you”A signature on a digest says:
- Sencai signed this exact content, and no other. A changed image has a different digest and no signature.
- The push came from an account that was allowed to push to your registry at the time. Pushes from any other account are refused and never signed.
- Who pushed it and when. The signed payload records your organization, the pusher (a member, or your CI credential), the time of the push and the fingerprint of the signing key.
- For an image pushed by a job on a hosted runner, which run and which commit built it. These two fields are present only when the push was tied to exactly one job; they are absent from images pushed any other way.
It does not say the image is free of vulnerabilities (that is what the scan is for) or that the code inside is what you meant to build. It proves identity and integrity, not quality.
Each image also carries a signed scan attestation: the scan result, signed with the same key, so a result you hold can be checked as genuine and tied to one digest.
Get your public key
Section titled “Get your public key”Your organization’s public key is a normal cosign public key file. It is named
after your organization’s short name, for example sencai-acme-cosign.pub.
- Open Registry and select the Sencai tab.
- Open any image. The Signing keys card lists every key version with its
algorithm, its SHA-256 fingerprint, when it was pinned and whether it is
retired, with a Download button per version. The Prove what you
deployed card has a Public key (
sencai-acme-cosign.pub) button that downloads the key that signed the version you are looking at.
Keep the file under the name it is downloaded with: the commands the image
page shows use that name. The key of an older version is downloaded as, for
example, sencai-acme-cosign-v1.pub. Anyone who can read your organization’s
registry can download the key, auditors included. Until the first image of
yours has been signed there is no key, and the card says so.
Always fetch the key from the app while you are signed in, not from a copy you found elsewhere, and keep the fingerprint from the page next to the file so you can compare. A verification is only as trustworthy as the key it uses.
Verify an image
Section titled “Verify an image”You need cosign: version 2.6 or later
in the 2.x line, or version 3.x. Take the digest from the image page and verify
by digest, never by tag - a tag can be moved, a digest cannot. The examples use
acme as the organization and sencai-acme-cosign.pub as the key file:
cosign verify \ --key sencai-acme-cosign.pub \ --insecure-ignore-tlog=true \ --new-bundle-format=false \ git.sencai.space/acme/api@sha256:<digest>A passing run prints the signed payload and ends with a line confirming the claims and the signature were verified. The Prove what you deployed card on the image page shows the exact command for the version you have selected, ready to copy. For a multi-platform image, select a platform in the Platforms table to get the command for that platform image. The key file in a command is the one for the key version that signed that image: an image signed before a key rotation is verified with the older key file, not the newest.
To check the scan attestation as well:
cosign verify-attestation \ --key sencai-acme-cosign.pub \ --type vuln \ --insecure-ignore-tlog=true \ --new-bundle-format=false \ git.sencai.space/acme/api@sha256:<digest>The attestation is only present once the first scan has finished, and there is one per platform image. It carries the findings, the scanner and vulnerability data versions, and the time of the scan. If the image has more than ten thousand findings, the attestation lists the first ten thousand by severity and says so. It is refreshed on the first scan and on rescans you start yourself with Scan again, not by the automatic weekly rescan, so check its scan time before relying on it as current. Because it holds the findings, the attestation can only be downloaded by people with access to security findings.
Verifying needs a registry credential that can pull (see Access). If you only want to check a signature and have no registry access, use the offline check below.
Why the two extra flags
Section titled “Why the two extra flags”--insecure-ignore-tlog=true- cosign normally expects a signature to be recorded in a public transparency log. Sencai does not publish to one: it would make the name of every private image public. The name of the flag sounds alarming, but what protects you here is your organization’s key, which you downloaded yourself and which only Sencai can sign with. Nothing about your images leaves the platform.--new-bundle-format=false- Sencai stores signatures the way cosign 2 did, as tags next to the image, not as the newer bundles in cosign 3’s default format. Both cosign 2.6 and cosign 3 verify this format with the flag. cosign 3 prints a warning that the flag is deprecated and that the newer format will be the only one in future versions; the verification still works today. If a later cosign release stops supporting the older format, verify with a release that still does (2.6.x, or the 3.x you have verified with).
Verify offline, without registry access
Section titled “Verify offline, without registry access”An auditor or a customer who has no registry credential can still verify a signature, because the signed material is available from the app.
- On the image page, in the Prove what you deployed card, download the signature material for the digest: payload.json (the signed payload) and sig.b64 (the signature), and the public key.
- Verify the signature with your public key:
cosign verify-blob \ --key sencai-acme-cosign.pub \ --signature sig.b64 \ --insecure-ignore-tlog=true \ payload.json- Open
payload.jsonand comparecritical.image.docker-manifest-digestwith the digest your runtime reports (next section). They must be identical.
The first step proves the payload was signed by your key; the second step proves the payload is about the image that is running. You need both. Download the material from the page of the digest you are comparing: for a multi-platform image that is the digest your runtime reports, which may be the index or one of its platform images (Sencai signs both).
If the image has a scan attestation and you can read security findings, the same card offers envelope.json, the signed attestation, so an auditor can keep it with the rest of the evidence.
Check which digest is running
Section titled “Check which digest is running”Compare the signed digest with what your servers actually run. Look at the image of the running container, not at the tag you started it from: a tag can point at a newer image than the one running.
Docker
docker inspect --format '{{.Image}}' <container>docker image inspect <image-id-from-above> --format '{{json .RepoDigests}}'Kubernetes
kubectl get pod <pod-name> -o jsonpath='{.status.containerStatuses[*].imageID}'The value after @ is the digest. Runtimes usually report the digest that the
image reference resolved to when it was pulled. For a multi-platform image that
is usually the digest of the index, but some runtimes report the digest of the
platform image they pulled (for example linux/amd64). Sencai signs both, so
download the signature material for whichever digest your runtime reports; if
you take the other one, the digests will not match even though the image is
the same.
If you report deployments to Sencai with the image reference and digest, the
Deployments timeline shows the image’s signature
and scan state next to the deployment record. Pull by digest in your manifests
(image: git.sencai.space/acme/api@sha256:...) so a deployment runs exactly
the content you verified, even if a tag is moved later. An image that only a
digest points to is not rescanned automatically; use Scan again on it from
time to time.
Servers that Sencai deploys verify it for you
Section titled “Servers that Sencai deploys verify it for you”When you deploy an image of your registry to a new
instance, the server checks the image’s signature itself before
it runs anything. It uses your organization’s public key (the one this page tells you to
download) and the digest that was ordered, with the same cosign verify check as above. If
the check fails, nothing starts, the deploy shows The signature check failed on the
server, and the members with access to security findings are notified. Only a signed
version can be chosen in the wizard in the first place.
That check happens once, at deploy time. It does not keep watching the server, so use the commands above to check a running server later.
When an image is not signed
Section titled “When an image is not signed”| What you see | What it means | What to do |
|---|---|---|
| Signing… | Normal for a minute or two after a push | Wait |
| Not signed — pushed by an account that may not push here | The pusher had no permission to push at that time. For a push from a hosted CI job this also covers a push that cannot be tied to the live job it came from, or whose triggering person may no longer push. The image is never signed, and the members who have access to security findings are notified | Push the image again from an authorized account, from your CI credential, or from a new run of the job |
| Signature removed — re-signing / Signature changed — re-signing | Someone deleted or replaced the signature objects that sit next to the image (tags that start with sha256- and end in .sig or .att). Sencai usually notices within 15 minutes and is attaching the signature again |
Nothing. A changed signature is also recorded in the audit log and the members with access to security findings are notified. Do not delete those tags yourself |
Signing failed (<reason>), retrying at <time> / Gave up after N attempts |
Signing hit a temporary problem, such as the signing service being unavailable | Wait for the retry, or use Sign again once the reason is resolved |
| Not signed — signing key check failed | The key on record for your organization no longer matches the key Sencai signs with. Sencai stops signing for your organization and the security contacts are notified | Contact support |
| Signing is not enabled in this environment | The environment you use has not switched signing on | Not an image problem |
Keys and rotation
Section titled “Keys and rotation”Your organization’s key is created automatically the first time an image of yours is signed, and the private half never leaves Sencai’s secret store: it is not exportable. Only the public half is available to you.
If Sencai rotates your key, the new version is added and published next to the old ones. Signatures made earlier stay valid and still verify with the version they were made with; the signed payload names the fingerprint of the version used. Keep every version you download.
If you delete the organization, its signatures and the records of its signing keys are deleted with it, together with the rest of its registry data. Download the public keys and any signature material you want to keep before deleting; nothing is taken for you.
Who can do what
Section titled “Who can do what”Reading images, downloading the key and downloading signature material need the registry Read permission, which every role including Viewer and Auditor has by default; the signed attestation needs access to security findings as well. Sign again needs Update. See Who can do what.
What’s next
Section titled “What’s next”- Container registry - tokens, what happens on every push, and what each status means
- Push images from CI - a hosted job pushes and the signature names its run
- Deploy a container to a new instance - the server verifies the signature before it runs the image
- Deployments - record which image each deployment shipped
- Audit log - signing, refused pushes and changed signatures are recorded here