Skip to main content
reliability · kubernetes

Workloads pulling container images tagged latest or with no tag at all

resource types
3
rule IDs covered
9
severity
medium

What does ZopNight detect here?

ZopNight flags Deployments, StatefulSets and DaemonSets on EKS, GKE and AKS when any container or init container uses an image tagged `:latest` or no tag. Kubernetes treats a missing tag as `latest` and pulls with `imagePullPolicy: Always` by default, so the same manifest can run different code on each node.

Signal and threshold

How ZopNight evaluates Workloads pulling container images tagged latest or with no tag at all.
Field Value
Rule IDsRC-1711 · RC-1811 · RC-1911 · RC-1712 · RC-1812 · RC-1912 · RC-1713 · RC-1813 · RC-1913
Categoryreliability
Severitymedium
Metriccontainer image reference
Thresholdtag is latest or absent; digests pass
SourceZopNight
Permissions usedlist deployments.apps · list statefulsets.apps · list daemonsets.apps

One tag, many possible images

A tag is a movable label. The container images documentation states that if you don’t specify a tag, Kubernetes assumes latest, and it warns against using :latest in production because it is harder to track which version is running and harder to roll back.

The pull policy makes it worse. When imagePullPolicy is omitted and the tag is latest or missing, Kubernetes sets the policy to Always. Every new pod asks the registry for whatever latest means at that moment. A node replaced on Tuesday can run a different build from the one that started on Monday, from the same unchanged manifest. A rollback to the previous ReplicaSet does not bring the old code back either, because the old ReplicaSet points at the same tag.

Searching workloads for unpinned images

The command checks main and init containers and treats digest references (@sha256:...) as pinned:

Terminal window
kubectl get deployments,statefulsets,daemonsets -A -o json | jq -r '
.items[] | .kind as $k | .metadata as $m
| (.spec.template.spec.containers + (.spec.template.spec.initContainers // []))[]
| select((.image | contains("@") | not)
and ((.image | split("/") | last | contains(":") | not)
or (.image | endswith(":latest"))))
| "\($k) \($m.namespace)/\($m.name) \(.name) \(.image)"'

How ZopNight parses each image reference

For every container, including init containers, ZopNight reads the image string. A reference containing @ is a digest and passes. Otherwise it looks for a tag after the last /, so a registry port such as registry.example:5000/app is not mistaken for a tag. No tag, or a tag equal to latest, marks the container. The finding lists every offending container by name, so an app container and a sidecar with the same problem appear on one recommendation. The check runs for Deployments, StatefulSets and DaemonSets on EKS, GKE and AKS, with no metric or time window.

Why init containers are in scope here

Several other workload checks, such as the probe and resource rules, skip init containers because those containers run once and exit. Image pinning is different: an init container pulls and executes a real image before the app starts, so an unpinned migration or setup image is just as unpredictable. Workloads with no containers in their spec are skipped. Tags such as stable or v1 that are moved in place are not detected, since only latest and missing tags are flagged.

Reliability risk, no savings figure

This medium-severity reliability finding has no dollar amount. The cost is unreproducible deploys, rollbacks that do not roll back and incidents that are hard to trace to a build.

Pinning every image

  1. Find the exact build running today with kubectl get pods -n <namespace> -o jsonpath='{..imageID}', which shows the digest each node pulled.
  2. Replace the tag with a version tag or a digest, for example kubectl set image deployment/api app=registry.example/api:1.42.0.
  3. Change CI so every build publishes an immutable version tag and the manifests reference it.
  4. Optionally enforce the rule at admission with a policy that rejects :latest.

See it fire on your bill.

Connect an account read-only. The first findings land in minutes.

472 rule families across 353 resource types on 22 platforms. Every threshold, metric, and IAM action is documented on these pages before you grant anything.

472 rule families documented
353 resource types covered
read-only default access level
Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console· Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console·