Back to Checks
image

'apt-get' missing '--no-install-recommends'

image_DS-0029
Service: dockerSeverity: high
OfficialBuilt-inVerified

'apt-get' install should use '--no-install-recommends' to minimize image size.

Run this check with Prowler

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

Recommendation

Add '--no-install-recommends' flag to 'apt-get'

Check Code

# METADATA
# title: "'apt-get' missing '--no-install-recommends'"
# description: "'apt-get' install should use '--no-install-recommends' to minimize image size."
# scope: package
# related_resources:
# - https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
# schemas:
# - input: schema["dockerfile"]
# custom:
#   id: DS-0029
#   long_id: docker-use-apt-no-install-recommends
#   aliases:
#     - AVD-DS-0029
#     - DS029
#     - use-apt-no-install-recommends
#     - docker-use-apt-no-install-recommends
#   severity: HIGH
#   recommended_action: "Add '--no-install-recommends' flag to 'apt-get'"
#   input:
#     selector:
#     - type: dockerfile
package builtin.dockerfile.DS029

import rego.v1

import data.lib.docker

deny contains res if {
	output := get_apt_get[_]
	msg := sprintf("'--no-install-recommends' flag is missed: '%s'", [output.arg])
	res := result.new(msg, output.cmd)
}

get_apt_get contains output if {
	run = docker.run[_]

	count(run.Value) == 1
	arg := run.Value[0]

	is_apt_get(arg)

	not includes_no_install_recommends(arg)

	output := {
		"arg": arg,
		"cmd": run,
	}
}

# checking json array
get_apt_get contains output if {
	run = docker.run[_]

	count(run.Value) > 1

	arg := concat(" ", run.Value)

	is_apt_get(arg)

	not includes_no_install_recommends(arg)

	output := {
		"arg": arg,
		"cmd": run,
	}
}

is_apt_get(command) if {
	regex.match("apt-get (-(-)?[a-zA-Z]+ *)*install(-(-)?[a-zA-Z]+ *)*", command)
}

no_install_flag := `--no-install-recommends`

optional_not_related_flags := `\s*(-(-)?[a-zA-Z]+\s*)*`

# https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-source
# https://www.debian.org/doc/debian-policy/ch-controlfields.html#version
pkgs := `([a-z\d][a-z\d+\-.]+(?:=[\w.+\-~:]+)?\s*)*`

combined_flags := sprintf(`%s%s%s`, [optional_not_related_flags, no_install_flag, optional_not_related_flags])

# flags before command
includes_no_install_recommends(command) if {
	install_regexp := sprintf(`apt-get%sinstall`, [combined_flags])
	regex.match(install_regexp, command)
}

# flags behind command
includes_no_install_recommends(command) if {
	install_regexp := sprintf(`apt-get%sinstall%s`, [optional_not_related_flags, combined_flags])
	regex.match(install_regexp, command)
}

# flags after pkgs
includes_no_install_recommends(command) if {
	install_regexp := sprintf(`apt-get%sinstall%s%s%s`, [optional_not_related_flags, optional_not_related_flags, pkgs, combined_flags])
	regex.match(install_regexp, command)
}