aquasecurity / trivy

Find vulnerabilities, misconfigurations, secrets, SBOM in containers, Kubernetes, code repositories, clouds and more
https://aquasecurity.github.io/trivy
Apache License 2.0
22.86k stars 2.25k forks source link

bug(misconf): Apply AVD-DS-0011 only to final layer #7368

Open simar7 opened 3 weeks ago

simar7 commented 3 weeks ago

Discussed in https://github.com/aquasecurity/trivy/discussions/7320

Originally posted by **candrews** August 8, 2024 ### IDs ds016 ### Description Trivy misconfiguration scan incorrectly reports duplicate CMD instructions for some docker images. Trivy seems to be looking for `CMD` instructions in all of the layers of the docker image. Instead, it should only be looking at the final image. Here's an example: ``` $ docker run -it aquasec/trivy:0.54.1 image --scanners misconfig --image-config-scanners misconfig registry.access.redhat.com/ubi8/python-312:1-16.1721725207 registry.access.redhat.com/ubi8/python-312:1-16.1721725207 (dockerfile) Tests: 28 (SUCCESSES: 24, FAILURES: 4, EXCEPTIONS: 0) Failures: 4 (UNKNOWN: 0, LOW: 1, MEDIUM: 0, HIGH: 1, CRITICAL: 2) CRITICAL: Slash is expected at the end of COPY command argument '$STI_SCRIPTS_PATH' ══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════ When a COPY command has more than two arguments, the last one should end with a slash. See https://avd.aquasec.com/misconfig/ds011 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registry.access.redhat.com/ubi8/python-312:1-16.1721725207:66 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── 66 [ COPY dir:bbef9bf403af8fa6579452e0550bf6bb61326be94d87e66c82243095f8aeb446 in $STI_SCRIPTS_PATH ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── CRITICAL: Slash is expected at the end of COPY command argument '/opt/wheels' ══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════ When a COPY command has more than two arguments, the last one should end with a slash. See https://avd.aquasec.com/misconfig/ds011 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registry.access.redhat.com/ubi8/python-312:1-16.1721725207:68 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── 68 [ COPY dir:5e283e09fcde7e88f28a5bf961c010f21e93095558bf27569a97b3a49fb19e30 in /opt/wheels ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── HIGH: There are 3 duplicate CMD instructions ══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════ There can only be one CMD instruction in a Dockerfile. If you list more than one CMD then only the last CMD will take effect. See https://avd.aquasec.com/misconfig/ds016 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registry.access.redhat.com/ubi8/python-312:1-16.1721725207:35 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── 35 [ CMD ["base-usage"] ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── LOW: Add HEALTHCHECK instruction in your Dockerfile ══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════ You should add HEALTHCHECK instruction in your docker container images to perform the health check on running containers. See https://avd.aquasec.com/misconfig/ds026 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── ``` The `Dockerfile` for this image can be seen at https://catalog.redhat.com/software/containers/ubi8/python-312/657c12cade3664622a12ed50?container-tabs=dockerfile - it contains exactly 1 `CMD` so it does not violate the https://avd.aquasec.com/misconfig/ds016 rule. ### Reproduction Steps ```bash 1. `docker run -it aquasec/trivy:0.54.1 image --scanners misconfig --image-config-scanners misconfig registry.access.redhat.com/ubi8/python-312:1-16.1721725207` Actual: "HIGH: There are 3 duplicate CMD instructions" is reported Expected: No such finding should be reported ``` ### Target Container Image ### Scanner Misconfiguration ### Target OS _No response_ ### Debug Output ```bash $ docker run -it aquasec/trivy:0.54.1 image --debug --scanners misconfig --image-config-scanners misconfig registry.access.redhat.com/ubi8/python-312:1-16.1721725207 2024-08-08T18:38:05Z DEBUG Cache dir dir="/root/.cache/trivy" 2024-08-08T18:38:05Z DEBUG Parsed severities severities=[UNKNOWN LOW MEDIUM HIGH CRITICAL] 2024-08-08T18:38:05Z DEBUG Ignore statuses statuses=[] 2024-08-08T18:38:05Z INFO [image] Container image config scanners scanners=[misconfig] 2024-08-08T18:38:05Z INFO [misconfig] Misconfiguration scanning is enabled 2024-08-08T18:38:05Z DEBUG Failed to open the check metadata err="open /root/.cache/trivy/policy/metadata.json: no such file or directory" 2024-08-08T18:38:05Z INFO Need to update the built-in policies 2024-08-08T18:38:05Z INFO Downloading the built-in policies... 2024-08-08T18:38:05Z DEBUG Loading check bundle repository="ghcr.io/aquasecurity/trivy-checks:0" 74.86 KiB / 74.86 KiB [-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------] 100.00% ? p/s 0s 2024-08-08T18:38:05Z DEBUG Digest of the built-in policies digest="sha256:ef2d9ad4fce0f933b20a662004d7e55bf200987c180e7f2cd531af631f408bb3" 2024-08-08T18:38:05Z DEBUG [misconfig] Policies successfully loaded from disk 2024-08-08T18:38:05Z DEBUG Enabling misconfiguration scanners scanners=[azure-arm cloudformation dockerfile helm kubernetes terraform terraformplan-json terraformplan-snapshot] 2024-08-08T18:38:05Z DEBUG Initializing scan cache... type="fs" 2024-08-08T18:38:07Z DEBUG [image] Detected image ID image_id="sha256:5d3de3428a507c1567a2bb2fe4f5bda919ac8babb04b621538b74d7fd265f3ff" 2024-08-08T18:38:07Z DEBUG [image] Detected diff ID diff_ids=[sha256:41fdab9a4e32b1a427aef2d9537ed8c34cae55ba76471c1a3b1e2a31819dacd6 sha256:09057cb70b4cc786df3b5a67120db8120d9ae445772ef020c90ad01af2b44032 sha256:4e29796b4201fba751b920fb5db529ac2be5dc80ea177b53d7c6e89a3cdc0e03 sha256:a8119cf37e14df02ad14d42e557dd886b3345c3859f2a568018e9f090411c5da] 2024-08-08T18:38:07Z DEBUG [image] Detected base layers diff_ids=[] 2024-08-08T18:38:07Z DEBUG [image] Missing image ID in cache image_id="sha256:5d3de3428a507c1567a2bb2fe4f5bda919ac8babb04b621538b74d7fd265f3ff" 2024-08-08T18:38:07Z DEBUG [image] Missing diff ID in cache diff_id="sha256:41fdab9a4e32b1a427aef2d9537ed8c34cae55ba76471c1a3b1e2a31819dacd6" 2024-08-08T18:38:07Z DEBUG [image] Missing diff ID in cache diff_id="sha256:09057cb70b4cc786df3b5a67120db8120d9ae445772ef020c90ad01af2b44032" 2024-08-08T18:38:07Z DEBUG [image] Missing diff ID in cache diff_id="sha256:4e29796b4201fba751b920fb5db529ac2be5dc80ea177b53d7c6e89a3cdc0e03" 2024-08-08T18:38:07Z DEBUG [image] Missing diff ID in cache diff_id="sha256:a8119cf37e14df02ad14d42e557dd886b3345c3859f2a568018e9f090411c5da" 2024-08-08T18:38:26Z INFO [python] License acquired from METADATA classifiers may be subject to additional terms name="chardet" version="3.0.4" 2024-08-08T18:38:26Z INFO [python] License acquired from METADATA classifiers may be subject to additional terms name="decorator" version="4.2.1" 2024-08-08T18:38:26Z INFO [python] License acquired from METADATA classifiers may be subject to additional terms name="idna" version="2.5" 2024-08-08T18:38:26Z INFO [python] License acquired from METADATA classifiers may be subject to additional terms name="iniparse" version="0.4" 2024-08-08T18:38:26Z INFO [python] License acquired from METADATA classifiers may be subject to additional terms name="pyinotify" version="0.9.6" 2024-08-08T18:38:26Z INFO [python] License acquired from METADATA classifiers may be subject to additional terms name="python-dateutil" version="2.6.1" 2024-08-08T18:38:26Z INFO [python] License acquired from METADATA classifiers may be subject to additional terms name="requests" version="2.20.0" 2024-08-08T18:38:26Z INFO [python] License acquired from METADATA classifiers may be subject to additional terms name="setuptools" version="39.2.0" 2024-08-08T18:38:26Z INFO [python] License acquired from METADATA classifiers may be subject to additional terms name="six" version="1.11.0" 2024-08-08T18:38:26Z INFO [python] License acquired from METADATA classifiers may be subject to additional terms name="urllib3" version="1.24.2" 2024-08-08T18:38:26Z INFO [python] License acquired from METADATA classifiers may be subject to additional terms name="dbus-python" version="1.2.4" 2024-08-08T18:38:26Z INFO [python] License acquired from METADATA classifiers may be subject to additional terms name="ethtool" version="0.14" 2024-08-08T18:38:26Z INFO [python] License acquired from METADATA classifiers may be subject to additional terms name="gpg" version="1.13.1" 2024-08-08T18:38:26Z INFO [python] License acquired from METADATA classifiers may be subject to additional terms name="libcomps" version="0.1.18" 2024-08-08T18:38:26Z INFO [python] License acquired from METADATA classifiers may be subject to additional terms name="PyGObject" version="3.28.3" 2024-08-08T18:38:26Z INFO [python] License acquired from METADATA classifiers may be subject to additional terms name="subscription-manager" version="1.28.42" 2024-08-08T18:38:26Z INFO [python] License acquired from METADATA classifiers may be subject to additional terms name="systemd-python" version="234" 2024-08-08T18:38:28Z INFO [python] License acquired from METADATA classifiers may be subject to additional terms name="pip" version="23.2.1" 2024-08-08T18:38:28Z INFO [python] License acquired from METADATA classifiers may be subject to additional terms name="pip" version="23.2.1" 2024-08-08T18:38:28Z DEBUG Scanning files for misconfigurations... scanner="Helm" 2024-08-08T18:38:28Z DEBUG [misconf] 38:28.426511724 helm.scanner.rego Overriding filesystem for checks! 2024-08-08T18:38:28Z DEBUG [misconf] 38:28.427211969 helm.scanner.rego Loaded 3 embedded libraries. 2024-08-08T18:38:28Z DEBUG [misconf] 38:28.458336582 helm.scanner.rego Loaded 192 embedded policies. 2024-08-08T18:38:28Z DEBUG [misconf] 38:28.497282492 helm.scanner.rego Loaded 195 checks from disk. 2024-08-08T18:38:28Z DEBUG [misconf] 38:28.497659261 helm.scanner.rego Overriding filesystem for data! 2024-08-08T18:38:33Z DEBUG Scanning files for misconfigurations... scanner="Helm" 2024-08-08T18:38:33Z DEBUG Scanning files for misconfigurations... scanner="Dockerfile" 2024-08-08T18:38:33Z DEBUG [misconf] 38:33.344126645 dockerfile.scanner.rego Overriding filesystem for checks! 2024-08-08T18:38:33Z DEBUG [misconf] 38:33.345946131 dockerfile.scanner.rego Loaded 3 embedded libraries. 2024-08-08T18:38:33Z DEBUG [misconf] 38:33.392725788 dockerfile.scanner.rego Loaded 192 embedded policies. 2024-08-08T18:38:33Z DEBUG [misconf] 38:33.444153749 dockerfile.scanner.rego Loaded 195 checks from disk. 2024-08-08T18:38:33Z DEBUG [misconf] 38:33.444480747 dockerfile.scanner.rego Overriding filesystem for data! 2024-08-08T18:38:33Z DEBUG [misconf] 38:33.725209384 dockerfile.scanner.rego Scanning 1 inputs... 2024-08-08T18:38:33Z DEBUG No secrets found in container image config 2024-08-08T18:38:33Z INFO Detected config files num=1 2024-08-08T18:38:33Z DEBUG Scanned config file file_path="registry.access.redhat.com/ubi8/python-312:1-16.1721725207" 2024-08-08T18:38:33Z DEBUG [vex] VEX filtering is disabled registry.access.redhat.com/ubi8/python-312:1-16.1721725207 (dockerfile) Tests: 28 (SUCCESSES: 24, FAILURES: 4, EXCEPTIONS: 0) Failures: 4 (UNKNOWN: 0, LOW: 1, MEDIUM: 0, HIGH: 1, CRITICAL: 2) CRITICAL: Slash is expected at the end of COPY command argument '$STI_SCRIPTS_PATH' ══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════ When a COPY command has more than two arguments, the last one should end with a slash. See https://avd.aquasec.com/misconfig/ds011 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registry.access.redhat.com/ubi8/python-312:1-16.1721725207:66 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── 66 [ COPY dir:bbef9bf403af8fa6579452e0550bf6bb61326be94d87e66c82243095f8aeb446 in $STI_SCRIPTS_PATH ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── CRITICAL: Slash is expected at the end of COPY command argument '/opt/wheels' ══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════ When a COPY command has more than two arguments, the last one should end with a slash. See https://avd.aquasec.com/misconfig/ds011 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registry.access.redhat.com/ubi8/python-312:1-16.1721725207:68 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── 68 [ COPY dir:5e283e09fcde7e88f28a5bf961c010f21e93095558bf27569a97b3a49fb19e30 in /opt/wheels ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── HIGH: There are 3 duplicate CMD instructions ══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════ There can only be one CMD instruction in a Dockerfile. If you list more than one CMD then only the last CMD will take effect. See https://avd.aquasec.com/misconfig/ds016 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registry.access.redhat.com/ubi8/python-312:1-16.1721725207:35 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── 35 [ CMD ["base-usage"] ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── LOW: Add HEALTHCHECK instruction in your Dockerfile ══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════ You should add HEALTHCHECK instruction in your docker container images to perform the health check on running containers. See https://avd.aquasec.com/misconfig/ds026 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── ``` ### Version ```bash 0.54.1 ``` ### Checklist - [X] Read [the documentation regarding wrong detection](https://aquasecurity.github.io/trivy/dev/community/contribute/discussion/#false-detection) - [X] Ran Trivy with `-f json` that shows data sources and confirmed that the security advisory in data sources was correct
knqyf263 commented 3 weeks ago

@simar7 @nikpivkin Does the misconfiguration scanner allow disabling checks by ID? When scanning image metadata, we want to pass AVD-DS-0011 as a disabled check.

simar7 commented 2 weeks ago

@simar7 @nikpivkin Does the misconfiguration scanner allow disabling checks by ID? When scanning image metadata, we want to pass AVD-DS-0011 as a disabled check.

@knqyf263 currently we don't but for my own understanding, I'd like to know how we can pass the info when scanning Dockerfiles to the misconf scanner, to purposefully ignore a check just for the image metadata.

From my understanding, we pass the Dockerfile as such. If we add another option in the misconfiguration scanner, how will the analyzer use it?

simar7 commented 2 weeks ago

It's certainly an interesting use case which I'd like to consider. It's more on the lines of disabling a check, but not completely ignoring it for all inputs. IOW, more granular than a simple selector or subtype based filter can accomplish today.

nikpivkin commented 2 weeks ago

@simar7 This is an interesting feature. It will disable the AVD-AWS-0169 check for all scanners except aws.

knqyf263 commented 2 weeks ago

I may be missing something, but I meant to pass DisableCheckIDs here. https://github.com/aquasecurity/trivy/blob/efdbd8f19ab0ab0c3b48293d43e51c81b7b03b89/pkg/fanal/analyzer/imgconf/dockerfile/dockerfile.go#L30

This analyze is used only when scanning image configuration (a.k.a. history) and doesn't need AVD-DS-0011.