# Dockerfile includes USER directive with non-root UID above 1000

- **Pattern:** `ab-001631` (`infrastructure-hardening.container-image-security.non-root-user`)
- **Severity:** critical
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001631
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001631)

## 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`:

```dockerfile
RUN useradd -m -u 1001 appuser
USER appuser
```

In your Kubernetes Deployment manifest (`k8s/deployment.yaml`):

```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 `USER` directive with UID above 1000 in Dockerfiles, or `securityContext.runAsNonRoot: true` with `runAsUser` above 1000 in Kubernetes manifests.
- **Pass criteria:** Every Dockerfile includes a `USER` directive specifying a non-root user with UID above 1000, and 100% of Kubernetes Deployment or StatefulSet manifests include `securityContext.runAsNonRoot: true` with explicit `runAsUser` above 1000. Report the ratio: "X of Y Dockerfiles and Z of W manifests enforce non-root."
- **Fail criteria:** Any Dockerfile runs as `root` or omits the USER directive (which defaults to root), or any Kubernetes manifest lacks `runAsNonRoot: 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-containers` check verifies that containers do not run with `securityContext.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`:

  ```dockerfile
  RUN useradd -m -u 1001 appuser
  USER appuser
  ```

  In Kubernetes, enforce it at the pod spec level in your Deployment manifest:

  ```yaml
  securityContext:
    runAsNonRoot: true
    runAsUser: 1001
    fsGroup: 1001
  ```

## External references

- cwe CWE-250
- nist AC-6
- external CIS-Docker-4.1 — https://www.cisecurity.org/benchmark/docker
- external CIS-Kubernetes-5.2.6 — https://www.cisecurity.org/benchmark/kubernetes

Taxons: operational-readiness, access-control

HTML version: https://auditbuffet.com/patterns/ab-001631
