Skip to main content

Docker Workload Attestor

The Docker attestor identifies workloads running inside Docker or Podman containers by querying the container runtime API. It discovers the container ID from the workload's cgroup path and uses it to fetch container metadata.

Configuration

Enable the Docker attestor in the WorkloadAttestation section:

section: WorkloadAttestation
schema: v1
spec:
docker:
enabled: true
FieldDefaultDescription
docker.enabledfalseEnable or disable Docker attestation
docker.dockerSocketPathunix:///var/run/docker.sockPath to the Docker daemon socket
docker.podmanSocketPathunix:///run/podman/podman.sockPath to the rootful Podman socket
docker.podmanSocketPathTemplateunix:///run/user/%d/podman/podman.sockTemplate for the rootless Podman socket path. Must contain exactly one %d placeholder, substituted with the workload user ID
docker.includeEnvVars[]Environment variable name prefixes to expose as docker.container.env.* attributes. When empty, no env var attributes are produced. Supports hot-reload
docker.sigstoreOptional. Configures Sigstore image-signature verification. See Sigstore Image Verification below.

The agent must have read access to the Docker or Podman socket. For rootless Podman, the agent requires sufficient privileges to read sockets owned by other users.

The attestor automatically detects whether to use Docker or Podman, including rootless Podman, without any additional configuration.

Environment variable filtering

By default, no environment variables are collected. Container env vars frequently contain secrets, so only variables whose name starts with a configured prefix are emitted as docker.container.env.* attributes.

section: WorkloadAttestation
schema: v1
spec:
docker:
enabled: true
includeEnvVars:
- APP_
- SERVICE_
- ENVIRONMENT

Matching is case-sensitive. With APP_VERSION=1.2.3 SERVICE_NAME=payments SECRET_KEY=abc ENVIRONMENT=prod, the above configuration emits APP_VERSION, SERVICE_NAME, and ENVIRONMENT. The SECRET_KEY variable is dropped.

Attributes

The following attributes are produced for successfully attested Docker and Podman containers and can be used in path templates, JWT custom claims, and X.509 Subject customization.

AttributeDescription
docker.container.imageImage ID string as recorded by the runtime, e.g. envoyproxy/envoy:v1.29.1
docker.container.label[<label_key>]One attribute per container label. The label key forms the last segment of the attribute name, e.g. docker.container.label["com.example.team"]
docker.container.env.<key>One attribute per environment variable matching an includeEnvVars prefix. Not produced unless includeEnvVars is configured
docker.container.image_config_digestContent-addressed image config digest, e.g. sha256:9f86d0…. Stable across image mirrors and re-tags. Omitted if the image inspect call fails
docker.image.signature.subjectIdentity that signed the image (e.g. a CI workflow URL or signer email). Only present when Sigstore is enabled and verification succeeds
docker.image.signature.issuerOIDC issuer that vouched for the signer. Only present when Sigstore is enabled and verification succeeds
docker.image.signature.valueBase64-encoded signature bytes. Only present when Sigstore is enabled and verification succeeds
docker.image.signature.log_idIdentifier of the Rekor instance that logged the entry. Omitted when skipTransparencyLog is true
docker.image.signature.log_indexMonotonic index of the entry within that Rekor instance. Omitted when skipTransparencyLog is true
docker.image.signature.integrated_timeUnix timestamp at which Rekor recorded the entry. Omitted when skipTransparencyLog is true
docker.image.signature.signed_entry_timestampRekor's signed inclusion promise for the entry. Omitted when skipTransparencyLog is true

Example SPIFFE ID template using a container label:

/workloads/{{docker.container.label["com.example.app"]}}
note

docker.container.image reflects the tag at container start time and can drift if the same tag is re-pushed. Use docker.container.image_config_digest in policies that require a pinned, immutable image identity.

Sigstore Image Verification

The Docker attestor can additionally verify Sigstore signatures on a workload's container image and expose the verified signature metadata as attestation attributes. Trust policies can then condition SVID issuance on who signed the image: For example, by specifying that production workloads must run an image signed by your release CI workflow.

Why Verify Image Signatures

Container registries are a supply-chain entry point. Attackers have published malicious images on Docker Hub under names that mimic real projects, hoping these images are pulled into production clusters. Sigstore mitigates this class of attack by letting image publishers cryptographically sign their images, and consumers verify those signatures before trusting the image. This applies equally to public images and to images your own CI builds for internal use.

When the agent verifies a signature, it records who signed it, which OIDC provider vouched for them, and proof from the Rekor transparency log that the signature was created while the signing certificate was valid. Trust policies can use these attributes to decide whether to issue an SVID at all, and what privileges that SVID carries.

Sigstore Attributes

When verification succeeds, the agent emits:

AttributeTypeDescription
docker.image.signature.subjectstringIdentity that signed the image (e.g. a CI workflow URL or signer email)
docker.image.signature.issuerstringOIDC issuer that vouched for the signer
docker.image.signature.valuestringBase64-encoded signature bytes
docker.image.signature.log_idstringIdentifier of the Rekor instance that logged the entry
docker.image.signature.log_indexuint64Monotonic index of the entry within that Rekor instance
docker.image.signature.integrated_timeuint64Unix timestamp at which Rekor recorded the entry
docker.image.signature.signed_entry_timestampstringRekor's signed inclusion promise for the entry
Gate on presence

These attributes are left out (omitted) whenever verification fails — see Failure Behavior. A missing subject is not a denial signal; it just means the agent did not produce a successful verification. Trust policies should require these attributes to be present in order to grant the privileges that depend on them.

Using Sigstore Attributes in Policy

The subject and issuer attributes are the primary handles for trust decisions. Use them together to pin both the signer and the IdP that issued their identity:

AttributeHow it's useful in a trust policy
subjectSpecify who must have signed the image — e.g. require a specific release CI workflow, not an arbitrary developer or unrelated workflow in the same org.
issuerPair with subject to also pin which IdP vouched for the signer — e.g. only accept identities issued by your corporate OIDC provider.
log_idRequire entries from a specific Rekor instance — e.g. only accept signatures logged in your private Rekor, not the public one.
integrated_timeEnforce recency — reject SVIDs whose images were signed before a known cutoff (e.g. a key-rotation event), or too long ago to be a fresh build.
log_indexReject entries below a cutoff index — useful for invalidating everything logged before a known incident without rotating the entire Rekor instance.
valueRarely used in policy directly. Most useful as an audit record of which signature was honored when the SVID was issued.
signed_entry_timestampRarely used in policy directly. Most useful as an audit artifact you can re-verify offline to prove the entry was in the log at issuance time.

Sigstore Configuration

Enable Sigstore verification under the docker block of the WorkloadAttestation section:

section: WorkloadAttestation
schema: v1
spec:
docker:
enabled: true
sigstore:
enabled: true
allowedIdentities: # Required.
# OIDC issuer URL → list of allowed subjects. Globbing supported in both.
"https://token.actions.githubusercontent.com":
- "https://github.com/myorg/myrepo/.github/workflows/release.yaml@refs/heads/main"
- "https://github.com/myorg/*/.github/workflows/release.yaml@refs/heads/main"
rekorURL: https://rekor.sigstore.dev # Optional, defaults to this.
skipProvenance: false # Optional, defaults to this.
skipTransparencyLog: false # Optional, defaults to this.
FieldDefaultDescription
sigstore.enabledRequired when the sigstore block is present. See enabled below.
sigstore.allowedIdentitiesRequired when enabled: true. Map of OIDC issuer URLs to allowed subjects. See allowedIdentities below.
sigstore.rekorURLhttps://rekor.sigstore.devRekor instance to use. See rekorURL below.
sigstore.skipProvenancefalseWhen false, a SLSA provenance attestation is also required. See skipProvenance below.
sigstore.skipTransparencyLogfalseWhen false, signatures are checked against Rekor. See skipTransparencyLog below.

Hot configuration reloads are supported. When applied via Managed Configuration, changes propagate live without an agent restart.

enabled

Set to true to turn on Sigstore verification. Required whenever the sigstore block is present — there is no implicit default.

allowedIdentities

A map of allowed OIDC issuer URLs to the list of subjects allowed under each. Must contain at least one issuer with at least one subject.

Patterns use globs rather than regular expressions, because it's much harder to write a glob that accidentally matches everything than it is to leave a regex unanchored:

  • * matches any sequence of characters, including none.
  • ? matches exactly one character.
  • The pattern is anchored: it must match the entire string.
  • Character classes, alternation, and other regex syntax are not supported.

To accept any subject from a given issuer, use ["*"]. Avoid this on a public issuer such as GitHub Actions — it allows any GitHub workflow in any organization to sign images you'll trust.

Anchor hostname patterns

A pattern like https://*.github.com* (note the trailing *) matches https://anything.github.com.attacker.example — almost certainly not what you want. Anchor the suffix: https://*.github.com/..., or omit the trailing wildcard.

rekorURL

The Rekor transparency-log instance the agent queries when verifying signatures. Defaults to the public Sigstore Rekor at https://rekor.sigstore.dev. Override only if you run your own instance. Must be an HTTPS URL.

skipProvenance

Controls whether the agent additionally verifies a SLSA provenance attestation after signature verification. See Provenance Attestations below for what provenance is and why it matters.

When false (default), a valid provenance attestation must exist and be signed by an identity matching allowedIdentities. If provenance verification fails, the entire docker.image.signature.* attribute set is rejected for that image.

When true, the provenance step is skipped. Use this for images that are signed (cosign sign) but don't have provenance — common outside highly regulated environments.

skipTransparencyLog

Controls whether signatures are verified against the Sigstore transparency log (Rekor).

When false (default), the agent checks Rekor to confirm the signature was created while the signing certificate was still valid. This is required for keyless signing with short-lived Fulcio certificates, which is the most common Sigstore setup.

When true, the Rekor check is skipped. Use this only if your images are signed with long-lived keys, or if you cannot reach the public Rekor and have configured a private instance via rekorURL.

warning

Setting skipTransparencyLog: true causes verification to fail for keyless-signed images. Only set it if you are not using keyless signing.

Provenance Attestations

A provenance attestation is a separate signed statement, stored alongside the image, that records facts about how the image was built — which commit, which CI workflow, which build runner. It's signed by your build system's identity (e.g. GitHub Actions), not by a developer.

Even if an attacker pushes a tampered image to your registry, they cannot forge the provenance from your CI signing identity. By default, the agent verifies both the signature and the provenance attestation against allowedIdentities before emitting any signature attributes. If your images are signed but do not have provenance, set skipProvenance: true.

Image publishers produce signatures with cosign sign and provenance with cosign attest; consumers verify them with cosign verify and cosign verify-attestation.

Operational Notes

Failure Behavior

Sigstore verification is fail-open with respect to attestation. If verification fails for any reason — image not signed, signature does not match allowedIdentities, Rekor unreachable, network timeout, missing provenance — the workload's attestation still succeeds, but the docker.image.signature.* attributes are omitted and a warning is logged.

This is intentional: a transient Rekor outage should not take down credential issuance for every workload. The implication is the same as the warning above — trust policies must require these attributes to be present, not check them for a "valid" flag.

Templates are an exception. If a path template, X.509 SVID template, or JWT claim references a docker.image.signature.* attribute and that attribute is absent, SVID issuance fails with a missing-attribute error rather than producing a malformed SVID. Reference these attributes from templates only on workloads where Sigstore verification is expected to succeed.

Verification Caching

Successful verifications are cached per image (by digest) with a 5-minute TTL. Failures are never cached.

Practical implications:

  • After publishing a new image, verification happens on the first attestation and is then served from cache for ~5 minutes.
  • If you tighten allowedIdentities to revoke a previously trusted signer, in-flight cached results may persist for up to 5 minutes. The cache is dropped when central config is reloaded.

Repo Digest Availability

Sigstore verification requires a repo digest — the registry/image@sha256:<digest> form produced when an image is pushed to a registry. Locally built images that have never been pushed will not have a repo digest, and verification is silently skipped.

Ensure images are pushed to a registry before deployment if Sigstore attributes are required by your policies.

Multiple Signatures

When an image has more than one valid signature matching allowedIdentities, only the first is used to populate attributes. A log line is emitted when this occurs.

Observability

When Sigstore attributes are not appearing as expected:

  1. Check the agent logs for warnings naming the image — every verification failure logs a reason.
  2. Inspect the Sigstore metrics described below to confirm the agent is attempting verification on the image you expect, and to see why it failed.
  3. Confirm the image has a repo digest — if the agent cannot resolve a digest, verification cannot run.

The agent emits the following Prometheus metrics. Every metric carries an attestor label (e.g. docker) so dashboards and alerts can be scoped to a single attestor.

MetricKey LabelsWhat it measures
spirl_agent_sigstore_image_verification_totalresult
attestor
Counter of verification attempts, classified by result
spirl_agent_sigstore_image_verification_duration_secondsresult
attestor
Histogram of how long each verification took, classified by result
spirl_agent_sigstore_signature_countattestorHistogram of valid signatures found per image — recorded only on successful verification
spirl_agent_sigstore_verification_cache_totalresult
attestor
Counter of cache lookups, where result is hit or miss

The result label on the two _image_verification_* metrics takes one of:

ValueMeaning
verifiedVerification succeeded
not_signedImage had no Sigstore signatures
identity_mismatchSignature did not match allowedIdentities
network_errorRegistry or Rekor network failure
timeoutVerification did not complete within the agent's deadline
cancelledContext cancelled (typically the workload disconnected)
errorAny other failure

As the cache fills, signature-count and verification-duration observations naturally fall in inverse proportion to the rise in cache_total{result="hit"} — a cache hit short-circuits the verification path.