RCE due to unpinned base image tag in Dockerfile

High Risk infrastructure-security
dockercontainer-securityimage-managementsupply-chainrcevulnerability-managementdockerfile

What it is

Docker containers built with unpinned base image tags like 'latest' or no tag specification create security vulnerabilities by potentially pulling vulnerable, outdated, or malicious images unpredictably. This nondeterministic behavior can introduce known CVEs and compromise container security during automated builds.

# VULNERABLE: Unpinned base images

# VULNERABLE: Using latest tag (implicit)
FROM node
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "start"]

# VULNERABLE: Using latest tag (explicit)
FROM alpine:latest
RUN apk add --no-cache curl
COPY script.sh /usr/local/bin/
CMD ["/usr/local/bin/script.sh"]

# VULNERABLE: Multi-stage with unpinned images
FROM golang:latest AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN go build -o main .

FROM alpine:latest
RUN apk --no-cache add ca-certificates
COPY --from=builder /app/main /usr/local/bin/
CMD ["main"]

# VULNERABLE: Using rolling/mutable tags
FROM ubuntu:rolling
RUN apt-get update && apt-get install -y python3
COPY app.py .
CMD ["python3", "app.py"]
# SECURE: Pinned base images

# SECURE: Node.js with specific version
FROM node:18.17.0-alpine3.18
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["npm", "start"]

# SECURE: Alpine with specific version
FROM alpine:3.18.4
RUN apk add --no-cache curl=8.3.0-r0
COPY script.sh /usr/local/bin/
CMD ["/usr/local/bin/script.sh"]

# SECURE: Multi-stage with pinned versions
FROM golang:1.21.3-alpine3.18 AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN go build -o main .

FROM alpine:3.18.4
RUN apk --no-cache add ca-certificates=20230506-r0
COPY --from=builder /app/main /usr/local/bin/
CMD ["main"]

# SECURE: Ubuntu LTS with specific version
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y \
    python3=3.10.6-1~22.04 && \
    rm -rf /var/lib/apt/lists/*
COPY app.py .
CMD ["python3", "app.py"]

# SECURE: Using SHA256 digest for immutability
FROM node:18.17.0-alpine3.18@sha256:a1ba21bf0c92931d02a8a2077d2b63bc344a4c8c8dfad81c5e6d98c8e8c4f9b5
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["npm", "start"]

💡 Why This Fix Works

The vulnerable configurations use 'latest' tags, omit tags entirely, or use rolling/mutable version tags that can change over time, potentially introducing security vulnerabilities or breaking changes in automated builds. The secure versions pin images to specific versions (e.g., node:18.17.0-alpine3.18) or SHA256 digests for maximum immutability, ensuring consistent and predictable base images. This prevents the container from pulling different image versions across builds and protects against supply chain attacks where malicious images could be pushed with the same tag.

Why it happens

Dockerfiles use 'latest' tag explicitly or omit tags entirely (which defaults to 'latest') in FROM statements. The 'latest' tag is mutable and can point to different images over time, introducing unpredictable vulnerabilities during builds.

Root causes

Latest Tag Usage

Dockerfiles use 'latest' tag explicitly or omit tags entirely (which defaults to 'latest') in FROM statements. The 'latest' tag is mutable and can point to different images over time, introducing unpredictable vulnerabilities during builds.

Mutable Tag Dependencies

Containers rely on mutable tags like 'stable', 'current', or version tags without patch numbers (e.g., 'node:18' instead of 'node:18.17.0'). These tags can change to point to newer versions containing unvetted security updates or new vulnerabilities.

Absent Image Pinning Strategy

Organizations lack documented image version management and pinning strategies. No processes ensure base images are explicitly versioned, leading to inconsistent, non-reproducible builds across environments.

Rolling and Edge Tag Usage

Dockerfiles reference rolling-release tags like 'edge', 'nightly', or 'rolling' which continuously update. These unstable tags introduce breaking changes and untested vulnerabilities into production container images.

Missing Immutable References

Containers don't use SHA256 digest-based image references which provide true immutability. Without digest pinning, even version tags can be overwritten or retagged, compromising build reproducibility and security.

Fixes

1

Pin to Specific Version Tags

Replace 'latest' and omitted tags with specific version numbers in Dockerfile FROM statements (e.g., 'alpine:3.18.4', 'node:18.17.0-alpine3.18'). Include major, minor, and patch versions for maximum specificity and predictability.

2

Use SHA256 Digest References

Reference images by immutable SHA256 digests rather than mutable tags (e.g., 'alpine@sha256:abc123...'). Digests provide cryptographic guarantees that the exact same image is pulled every time, preventing tag manipulation attacks.

3

Automate Dependency Updates

Implement automated tools like Dependabot, Renovate, or similar solutions to create pull requests for base image updates. This provides controlled, reviewable updates to pinned versions while maintaining security patching.

4

Maintain Multi-Stage Build Consistency

Ensure all stages in multi-stage Dockerfiles use pinned versions consistently. Pin both builder and runtime base images to specific versions to guarantee reproducible builds across all stages.

5

Establish Update Processes

Create documented processes for regularly reviewing and updating pinned image versions. Schedule periodic security reviews to update base images with CVE patches while maintaining version control and testing.

Detect This Vulnerability in Your Code

Sourcery automatically identifies rce due to unpinned base image tag in dockerfile and many other security issues in your codebase.