# CL-0004: Image Not Pinned to Version

**Severity:** MEDIUM

**References:**
- [OWASP Docker Security Rule #13](https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html#rule-13-enhance-supply-chain-security)
- CIS Docker Benchmark 5.28 — Ensure that Docker commands always make use of the latest version of their image

## What it detects

Services using mutable image tags (`latest`, `stable`, `edge`, `nightly`, `dev`, `test`) or no tag at all. Build-only services (no `image:` key) and digest-pinned images (`@sha256:...`) are skipped.

The mutable-tag list is a closed enumeration of well-known aliases. Tags like `main`, `master`, `release`, `prod`, `slim`, or `alpine` are also mutable in practice but are not flagged here — distinguishing "moving target" from "stable channel" requires registry knowledge the linter does not have. CL-0019 (digest pinning) is the stronger check; treat CL-0004 as catching the obvious cases.

## Why it matters

Mutable tags mean every pull can produce a different image. This breaks reproducibility, makes rollbacks impossible, and opens supply chain risk — a compromised upstream push to `latest` affects you on next deploy with no visibility into what changed.

## Fix

```yaml
# Instead of:
image: nginx:latest

# Pin to a specific version:
image: nginx:1.27-alpine
```

For maximum reproducibility, use digest pinning (CL-0019). Tag pinning protects against accidental version churn; digest pinning additionally protects against an attacker overwriting a tag in the registry. Cosign signature verification or registry-level immutability flags add a further layer if your registry supports them.

```yaml
image: nginx:1.27-alpine@sha256:...
```

Find current stable versions on Docker Hub or your registry.

## See also

- [CL-0019](CL-0019.md) — digest pinning (stronger guarantee against tag mutation)
