Back to Checks
image

Image user should not be 'root'

image_DS-0002
Service: dockerSeverity: high
OfficialBuilt-inVerified

Running containers with 'root' user can lead to a container escape situation. It is a best practice to run containers as non-root users, which can be done by adding a 'USER' statement to the Dockerfile.

Run this check with Prowler

Run in Prowler Cloud
Run
prowler image --checks image_DS-0002

Recommendation

Add 'USER <non root user name>' line to the Dockerfile

Check Code

# METADATA
# title: "Image user should not be 'root'"
# description: "Running containers with 'root' user can lead to a container escape situation. It is a best practice to run containers as non-root users, which can be done by adding a 'USER' statement to the Dockerfile."
# scope: package
# schemas:
# - input: schema["dockerfile"]
# related_resources:
# - https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
# custom:
#   id: DS-0002
#   long_id: docker-least-privilege-user
#   aliases:
#     - AVD-DS-0002
#     - DS002
#     - least-privilege-user
#     - docker-least-privilege-user
#   severity: HIGH
#   recommended_action: "Add 'USER <non root user name>' line to the Dockerfile"
#   input:
#     selector:
#     - type: dockerfile
#   examples: checks/docker/root_user.yaml
package builtin.dockerfile.DS002

import rego.v1

import data.lib.docker

# get_user returns all the usernames from
# the USER command.
get_user contains username if {
	user := docker.user[_]
	username := user.Value[_]
}

# fail_user_count is true if there is no USER command.
fail_user_count if {
	count(get_user) < 1
}

# fail_last_user_root is true if the last USER command
# value is "root"
fail_last_user_root contains lastUser if {
	users := [user | user := docker.user[_]]
	lastUser := users[count(users) - 1]
	regex.match("^root(:.+){0,1}$", lastUser.Value[0])
}

# fail_last_user_root is true if the last USER command
# value is "0"
fail_last_user_root contains lastUser if {
	users := [user | user := docker.user[_]]
	lastUser := users[count(users) - 1]
	regex.match("^0(:.+){0,1}$", lastUser.Value[0])
}

deny contains res if {
	fail_user_count
	msg := "Specify at least 1 USER command in Dockerfile with non-root user as argument"
	res := result.new(msg, {})
}

deny contains res if {
	cmd := fail_last_user_root[_]
	msg := "Last USER command in Dockerfile should not be 'root'"
	res := result.new(msg, cmd)
}