Dockerfile includes USER directive with non-root UID above 1000
Why it matters
Containers running as root (UID 0) violate the principle of least privilege (NIST 800-53 AC-6, CWE-250) and collapse the host boundary if any container escape vulnerability is exploited. A root container with a kernel exploit gains full control of the host node — every other workload on that node is compromised. CIS Docker 4.1 and CIS Kubernetes 5.2.6 both mandate non-root execution. The blast radius of a runtime compromise is bounded only when the container process has no privilege to exercise outside its own namespace.
Severity rationale
Critical because a container running as root combined with any container-escape vulnerability grants full host node access, compromising all co-located workloads.
Remediation
Add a dedicated unprivileged user in Dockerfile and enforce it in Kubernetes securityContext. In Dockerfile:
RUN useradd -m -u 1001 appuser
USER appuser
In your Kubernetes Deployment manifest (k8s/deployment.yaml):
spec:
template:
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1001
fsGroup: 1001
For distroless images that have no useradd, set USER 65532 (the nonroot user built into distroless). The UID must exceed 1000 to avoid collision with system accounts.
Detection
-
ID:
non-root-user -
Severity:
critical -
What to look for: Count every Dockerfile and Kubernetes Deployment/StatefulSet manifest. For each, check whether a non-root user is configured — a
USERdirective with UID above 1000 in Dockerfiles, orsecurityContext.runAsNonRoot: truewithrunAsUserabove 1000 in Kubernetes manifests. -
Pass criteria: Every Dockerfile includes a
USERdirective specifying a non-root user with UID above 1000, and 100% of Kubernetes Deployment or StatefulSet manifests includesecurityContext.runAsNonRoot: truewith explicitrunAsUserabove 1000. Report the ratio: "X of Y Dockerfiles and Z of W manifests enforce non-root." -
Fail criteria: Any Dockerfile runs as
rootor omits the USER directive (which defaults to root), or any Kubernetes manifest lacksrunAsNonRoot: true. -
Do NOT pass when: A USER directive is present but specifies UID 0 (root) or a UID below 1000 — the user must be truly unprivileged.
-
Skip (N/A) when: The project does not have containerization.
-
Cross-reference: The
no-privileged-containerscheck verifies that containers do not run withsecurityContext.privileged: true, which would override non-root restrictions. -
Detail on fail: Specify what was found. Example:
"Dockerfile does not include a USER directive — container runs as root"or"Kubernetes Deployment lacks securityContext.runAsNonRoot configuration" -
Remediation: Running as root allows any container escape vulnerability to compromise the host. Create a dedicated unprivileged user in
Dockerfile:RUN useradd -m -u 1001 appuser USER appuserIn Kubernetes, enforce it at the pod spec level in your Deployment manifest:
securityContext: runAsNonRoot: true runAsUser: 1001 fsGroup: 1001
External references
- cwe · CWE-250 — Execution with Unnecessary Privileges
- nist:rev5 · AC-6 — Least Privilege
- external · CIS-Docker-4.1 — CIS Docker Benchmark v1.6 §4.1 — Ensure a user for the container has been created
- external · CIS-Kubernetes-5.2.6 — CIS Kubernetes Benchmark §5.2.6 — Do not admit root containers
Taxons
History
- 2026-04-18·v1.0.0·Initial import from infrastructure-hardening·automated