Secrets in Dockerfile
Secrets added via ENV, ARG, or COPY .env in a Dockerfile are baked into the image layers and readable by anyone who pulls the image.
How It Works
Docker images are layered. Even if you delete a secret in a later RUN command, it's still readable in the previous layer via docker history or by extracting the image tarball. Anyone who pulls your image — including CI systems, registries, or unauthorized users — can extract it.
# BAD: secrets baked into image layers — permanent and extractable
FROM node:20-alpine
ENV DATABASE_URL=postgres://user:secret@host/db
ARG STRIPE_SECRET_KEY
COPY .env /app/.env # .env contents are in the layer forever# GOOD: use Docker BuildKit secrets for build-time values
# syntax=docker/dockerfile:1
FROM node:20-alpine
# Runtime secrets passed via environment at container run time, not baked in
# docker run -e DATABASE_URL=$DATABASE_URL myapp
# For build-time secrets: use --secret flag with BuildKit
RUN --mount=type=secret,id=npmrc,target=/root/.npmrc npm ciReal-World Example
In 2021, researchers scanning public Docker Hub images found thousands of images with hardcoded AWS credentials, database passwords, and API keys baked into image layers — including from Fortune 500 companies.
How to Prevent It
- Never use ENV or ARG to pass secrets into Docker images
- Use Docker BuildKit --secret mounts for build-time secrets (they don't appear in layers)
- Pass runtime secrets as environment variables at container start, not bake them in
- Scan images with Trivy or docker scout before pushing to any registry
Affected Technologies
Data Hogo detects this vulnerability automatically.
Scan Your Repo FreeRelated Vulnerabilities
Running as Root in Docker
mediumContainers that run as root give any code execution vulnerability immediate root access to the container — and potentially the host.
Docker Latest Tag
lowUsing FROM image:latest means a new pull can silently change your base image, breaking reproducibility and potentially introducing vulnerabilities.
Unnecessary Exposed Ports
lowEXPOSE-ing ports your application doesn't actually use increases the attack surface without any benefit.
No Docker Health Check
lowWithout a HEALTHCHECK instruction, Docker and orchestrators can't detect when your container is running but broken — routing traffic to a dead app.