Running as Root in Docker
Containers that run as root give any code execution vulnerability immediate root access to the container — and potentially the host.
How It Works
By default, Docker containers run as the root user inside the container. If an attacker exploits your app (e.g., via a command injection), they get root in the container. Combined with misconfigured volume mounts or Docker socket exposure, root in container often means root on the host.
# BAD: no USER instruction — runs as root by default
FROM node:20-alpine
WORKDIR /app
COPY . .
RUN npm ci
EXPOSE 3000
CMD ["node", "server.js"]# GOOD: create a non-root user and switch to it
FROM node:20-alpine
WORKDIR /app
COPY . .
RUN npm ci --only=production
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser
EXPOSE 3000
CMD ["node", "server.js"]Real-World Example
The 2019 runc container escape vulnerability (CVE-2019-5736) allowed root inside a container to overwrite the runc binary on the host. Containers running as non-root users were not affected by this class of attack.
How to Prevent It
- Always add a USER instruction to your Dockerfile with a non-root user
- Use addgroup and adduser in Alpine, or groupadd/useradd in Debian-based images
- Set --cap-drop=ALL in docker run to remove all capabilities, adding back only what's needed
- Use Docker's --read-only flag to make the container filesystem immutable where possible
Affected Technologies
Data Hogo detects this vulnerability automatically.
Scan Your Repo FreeRelated Vulnerabilities
Docker Latest Tag
lowUsing FROM image:latest means a new pull can silently change your base image, breaking reproducibility and potentially introducing vulnerabilities.
Secrets in Dockerfile
criticalSecrets added via ENV, ARG, or COPY .env in a Dockerfile are baked into the image layers and readable by anyone who pulls the image.
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.