Skip to content

Bug: Container Runs as Root User in Dockerfile #987

Description

@Reactivity512

Location:
ozontech/file.d/blob/master/build/package/Dockerfile
ozontech/file.d/blob/master/build/package/Dockerfile.scratch
ozontech/file.d/blob/master/build/package/Dockerfile_dev
ozontech/file.d/blob/master/build/package/Dockerfile_playground

Description:
All four Dockerfiles lack the USER instruction, causing the container to run as root (UID 0) by default. This violates the principle of least privilege (CWE-250). Even if a non-root user was created in previous build stages, it is not carried over to the final image; the USER instruction must be explicitly defined in the runtime stage.

Risk:

  • If any vulnerability leading to code execution is exploited (RCE, SSRF with command execution capabilities, writeable path traversal, etc.), an attacker gains full control over the container.
  • Root access within the container often allows an attacker to:
    • Install additional packages or malware,
    • Modify the host filesystem (if sensitive directories are mounted),
    • Bypass security restrictions in orchestrators (e.g., Kubernetes PodSecurityPolicies / Pod Security Admission).
  • Direct violation of security standards and benchmarks:
    • CIS Docker Benchmark 4.1,
    • OWASP Docker Security,
    • Kubernetes Pod Security Standards (Restricted profile).

Screenshot

Image

Empty value - run as root

Recommendations:

Add user creation and switch to the non-root user in the final stage of each Dockerfile:

# Example for Alpine-based images
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser

For the scratch-based image:

ARG APP_IMAGE=ubuntu:latest

# Build
FROM --platform=$BUILDPLATFORM golang:1.25-alpine AS build

RUN addgroup -S appgroup && adduser -S appuser -G appgroup

ARG VERSION
ARG BUILD_TIME
ARG TARGETARCH

WORKDIR /file.d

COPY go.mod go.sum ./

RUN go mod download

COPY . .

ENV CGO_ENABLED 0
ENV GOOS linux
ENV GOARCH ${TARGETARCH:-amd64}

RUN go build -trimpath \
    -pgo default.pgo \
    -ldflags "-X github.com/ozontech/file.d/buildinfo.Version=${VERSION}" \
    -o file.d ./cmd/file.d

# Deploy
FROM scratch

COPY --from=build /etc/passwd /etc/passwd
COPY --from=build /etc/group /etc/group
USER appuser

WORKDIR /file.d

COPY --from=build /file.d/file.d /file.d/file.d

CMD [ "./file.d" ]
Image

In Kubernetes manifests, enforce this by adding the securityContext:

securityContext:
  runAsNonRoot: true
  runAsUser: 1001

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions