Skip to main content

Trivy: A Swiss Army Knife for Security

trivy

Documentation

Github

It's a very powerful and versatile security scanner developed by Aqua Security. Extremely easy to use, an All In One command line that generates CVE reports for the following resources:

  • Container Images
  • Filesystem
  • Git Repositories
  • VM Images
  • Kubernetes
  • AWS

Supports the main languages, such as:

  • Golang
  • .Net
  • Java
  • NodeJs
  • Rust
  • Python

In addition to all this, we can analyze IaC declaration files in Terraform, Helm, Kubernetes manifests and cluster vulnerabilities, and Dockerfiles. Of course there are more specific tools for this subject, but in a basic way it does an excellent job making Trivy one of the Swiss army knives in the security world.

As we'll see below using Trivy we can scan several things. Each command will act differently.

alt text

Installation​

We can install the cli or run directly from a container.

No point reinventing the wheel. We can install using the package manager of the main distros, downloading the binary, using asdf, using the script, and cloning the repository. Check here how to install.

Since it's just a CLI we can use docker. The image already has the trivy entrypoint prepared to receive CLI parameters.

You only need to map the volumes -v /var/run/docker.sock:/var/run/docker.sock -v $HOME/Library/Caches:/root/.cache if you're going to scan images.

# docker run  aquasec/trivy also works

root@master:~# docker run -v /var/run/docker.sock:/var/run/docker.sock -v $HOME/Library/Caches:/root/.cache/ aquasec/trivy:0.55.0
Usage:
trivy [global flags] command [flags] target
trivy [command]

Examples:
# Scan a container image
$ trivy image python:3.4-alpine

# Scan a container image from a tar archive
$ trivy image --input ruby-3.1.tar

# Scan local filesystem
$ trivy fs .

# Run in server mode
$ trivy server


########### FUNCTIONALITY SEPARATION ##################
Scanning Commands
config Scan config files for misconfigurations
filesystem Scan local filesystem
image Scan a container image
kubernetes [EXPERIMENTAL] Scan kubernetes cluster
repository Scan a repository
rootfs Scan rootfs
sbom Scan SBOM for vulnerabilities and licenses
vm [EXPERIMENTAL] Scan a virtual machine image
###########################################################

Management Commands
module Manage modules
plugin Manage plugins
vex [EXPERIMENTAL] VEX utilities

Utility Commands
clean Remove cached files
completion Generate the autocompletion script for the specified shell
convert Convert Trivy JSON report into a different format
help Help about any command
server Server mode
version Print the version

Flags:
--cache-dir string cache directory (default "/root/.cache/trivy")
-c, --config string config path (default "trivy.yaml")
-d, --debug debug mode
-f, --format string version format (json)
--generate-default-config write the default config to trivy-default.yaml
-h, --help help for trivy
--insecure allow insecure server connections
-q, --quiet suppress progress bar and log output
--timeout duration timeout (default 5m0s)
-v, --version show version

Use "trivy [command] --help" for more information about a command.

Enable completion to check various possible parameters.

Container Analysis​

Let's start with the basic vulnerability scan on images. We can analyze an image we already have or it will download it.

trivy image <parameters> is the subcommand used to activate image scans.

# Using the latest version of trivy:latest scanning the latest version of alpine.

# Each time it will download the database so let's remove some output to improve readability
root@master:~# docker run aquasec/trivy image alpine
2024-09-04T01:14:19Z INFO [db] Need to update DB
2024-09-04T01:14:19Z INFO [db] Downloading DB... repository="ghcr.io/aquasecurity/trivy-db:2"
16.98 MiB / 52.71 MiB [------------------->_________________________________________] 32.21% ? p/s ?34.67 MiB / 52.71 MiB s ETA 0s52.71 MiB / 52.71 MiB [-------------------------------------------------] 100.00% 13.57 MiB p/s 4.1s2024-09-04T01:14:23Z INFO [vuln] Vulnerability scanning is enabled
2024-09-04T01:14:23Z INFO [secret] Secret scanning is enabled
2024-09-04T01:14:23Z INFO [secret] If your scanning is slow, please try '--scanners vuln' to disable secret scanning
2024-09-04T01:14:23Z INFO [secret] Please see also https://aquasecurity.github.io/trivy/v0.55/docs/scanner/secret#recommendation for faster secret detection
2024-09-04T01:14:25Z INFO Detected OS family="alpine" version="3.20.2"
2024-09-04T01:14:25Z INFO [alpine] Detecting vulnerabilities... os_version="3.20" repository="3.20" pkg_num=14
2024-09-04T01:14:25Z INFO Number of language-specific files num=0

alpine (alpine 3.20.2)
======================
Total: 0 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 0)
# Alpine is really great!

Do a test on other images like Ubuntu for example.

Let's go to Kubernetes to scan the apiserver 1.30.4

root@cks-master:~# docker run  aquasec/trivy image registry.k8s.io/kube-apiserver:v1.30.4
2024-09-04T01:20:19Z INFO [db] Need to update DB
2024-09-04T01:20:19Z INFO [db] Downloading DB... repository="ghcr.io/aquasecurity/trivy-db:2"
15.68 MiB / 52.71 MiB [------------------>__________________________________________] 29.74% ? p/s ?37.33 MiB / 52.71 MiB [-------------------------------------------------] 100.00% 16.18 MiB p/s 3.5s2024-09-04T01:20:23Z INFO [vuln] Vulnerability scanning is enabled
2024-09-04T01:20:23Z INFO [secret] Secret scanning is enabled
2024-09-04T01:20:23Z INFO [secret] If your scanning is slow, please try '--scanners vuln' to disable secret scanning
2024-09-04T01:20:23Z INFO [secret] Please see also https://aquasecurity.github.io/trivy/v0.55/docs/scanner/secret#recommendation for faster secret detection
2024-09-04T01:20:26Z INFO Detected OS family="debian" version="12.5"
2024-09-04T01:20:26Z INFO [debian] Detecting vulnerabilities... os_version="12" pkg_num=3
2024-09-04T01:20:26Z INFO Number of language-specific files num=2
2024-09-04T01:20:26Z INFO [gobinary] Detecting vulnerabilities...

registry.k8s.io/kube-apiserver:v1.30.4 (debian 12.5)
====================================================
Total: 0 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 0)


usr/local/bin/kube-apiserver (gobinary)
=======================================
Total: 2 (UNKNOWN: 0, LOW: 0, MEDIUM: 1, HIGH: 1, CRITICAL: 0)

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Library β”‚ Vulnerability β”‚ Severity β”‚ Status β”‚ Installed Version β”‚ Fixed Version β”‚ Title β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ go.opentelemetry.io/contrib/instrumentation/google.golang.o- β”‚ CVE-2023-47108 β”‚ HIGH β”‚ fixed β”‚ v0.42.0 β”‚ 0.46.0 β”‚ opentelemetry-go-contrib: DoS vulnerability in otelgrpc due β”‚
β”‚ rg/grpc/otelgrpc β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ to unbound cardinality metrics β”‚
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2023-47108 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ gopkg.in/square/go-jose.v2 β”‚ CVE-2024-28180 β”‚ MEDIUM β”‚ affected β”‚ v2.6.0 β”‚ β”‚ jose-go: improper handling of highly compressed data β”‚
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2024-28180 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
# Oops we found some things...

Well that's it, there are the CVEs found, if it's possible to fix or not. If you want to ignore those that can't be fixed just pass the -ignore-unfixed flag.

If you want to see lots of CVEs do a test on nginx. This time I'll run using the trivy cli.

# --ignore-unfixed will reduce output to only known and fixable CVEs.
trivy image nginx --ignore-unfixed
2024-09-03T22:32:41-03:00 INFO [vuln] Vulnerability scanning is enabled
2024-09-03T22:32:41-03:00 INFO [secret] Secret scanning is enabled
2024-09-03T22:32:41-03:00 INFO [secret] If your scanning is slow, please try '--scanners vuln' to disable secret scanning
2024-09-03T22:32:41-03:00 INFO [secret] Please see also https://aquasecurity.github.io/trivy/v0.54/docs/scanner/secret#recommendation for faster secret detection
2024-09-03T22:32:43-03:00 INFO Detected OS family="debian" version="12.6"
2024-09-03T22:32:43-03:00 INFO [debian] Detecting vulnerabilities... os_version="12" pkg_num=149
2024-09-03T22:32:43-03:00 INFO Number of language-specific files num=0
2024-09-03T22:32:43-03:00 WARN Using severities from other vendors for some vulnerabilities. Read https://aquasecurity.github.io/trivy/v0.54/docs/scanner/vulnerability#severity-selection for details.

nginx (debian 12.6)

Total: 9 (UNKNOWN: 0, LOW: 2, MEDIUM: 6, HIGH: 0, CRITICAL: 1)

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Library β”‚ Vulnerability β”‚ Severity β”‚ Status β”‚ Installed Version β”‚ Fixed Version β”‚ Title β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ curl β”‚ CVE-2024-7264 β”‚ MEDIUM β”‚ fixed β”‚ 7.88.1-10+deb12u6 β”‚ 7.88.1-10+deb12u7 β”‚ curl: libcurl: ASN.1 date parser overread β”‚
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2024-7264 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ libaom3 β”‚ CVE-2024-5171 β”‚ CRITICAL β”‚ β”‚ 3.6.0-1 β”‚ 3.6.0-1+deb12u1 β”‚ libaom: Integer overflow in internal β”‚
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ function img_alloc_helper β”‚
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2024-5171 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ libcurl4 β”‚ CVE-2024-7264 β”‚ MEDIUM β”‚ β”‚ 7.88.1-10+deb12u6 β”‚ 7.88.1-10+deb12u7 β”‚ curl: libcurl: ASN.1 date parser overread β”‚
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2024-7264 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ libssl3 β”‚ CVE-2024-4603 β”‚ β”‚ β”‚ 3.0.13-1~deb12u1 β”‚ 3.0.14-1~deb12u1 β”‚ openssl: Excessive time spent checking DSA keys and β”‚
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ parameters β”‚
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2024-4603 β”‚
β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ β”‚ CVE-2024-4741 β”‚ β”‚ β”‚ β”‚ β”‚ openssl: Use After Free with SSL_free_buffers β”‚
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2024-4741 β”‚
β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ β”‚ CVE-2024-2511 β”‚ LOW β”‚ β”‚ β”‚ β”‚ openssl: Unbounded memory growth with session handling β”‚
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ in TLSv1.3 β”‚
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2024-2511 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ openssl β”‚ CVE-2024-4603 β”‚ MEDIUM β”‚ β”‚ β”‚ β”‚ openssl: Excessive time spent checking DSA keys and β”‚
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ parameters β”‚
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2024-4603 β”‚
β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ β”‚ CVE-2024-4741 β”‚ β”‚ β”‚ β”‚ β”‚ openssl: Use After Free with SSL_free_buffers β”‚
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2024-4741 β”‚
β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ β”‚ CVE-2024-2511 β”‚ LOW β”‚ β”‚ β”‚ β”‚ openssl: Unbounded memory growth with session handling β”‚
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ in TLSv1.3 β”‚
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2024-2511 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Analyzing IaC​

Inside the directory a simple Dockerfile and a deployment.yaml

❯ cat Dockerfile
FROM alpine
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y golang-go
COPY app.go .
RUN go build app.go
CMD ["./app"]

#Creating the deployment.yaml
❯ kubectl create deployment nginx --image=nginx -oyaml --dry-run=client > deployment.yaml

❯ cat deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: nginx
name: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: nginx
spec:
containers:
- image: nginx
name: nginx
resources: {}
status: {}

Let's analyze the current folder we are in. I'll comment on this output.

❯ trivy config .
2024-09-03T23:31:25-03:00 INFO [misconfig] Misconfiguration scanning is enabled
2024-09-03T23:31:26-03:00 INFO Detected config files num=2

# Found a dockerfile
Dockerfile (dockerfile)

Tests: 27 (SUCCESSES: 23, FAILURES: 4, EXCEPTIONS: 0)
Failures: 4 (UNKNOWN: 0, LOW: 1, MEDIUM: 1, HIGH: 2, CRITICAL: 0)

MEDIUM: Specify a tag in the 'FROM' statement for image 'alpine' # Good, because we didn't define any specific version
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
When using a 'FROM' statement you should use a specific tag to avoid uncontrolled behavior when the image is updated.

See https://avd.aquasec.com/misconfig/ds001
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Dockerfile:1
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 [ FROM alpine
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

# Good, because we didn't define any USER
HIGH: Specify at least 1 USER command in Dockerfile with non-root user as argument
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
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.

See https://avd.aquasec.com/misconfig/ds002
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

# Good because it's not good practice to have container HEALTHCHECK.
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
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

# Very good....
HIGH: '--no-install-recommends' flag is missed: 'apt-get update && apt-get install -y golang-go'
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
'apt-get' install should use '--no-install-recommends' to minimize image size.

See https://avd.aquasec.com/misconfig/ds029
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Dockerfile:3
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
3 [ RUN apt-get update && apt-get install -y golang-go
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

# Now analyzing the other file...

deployment.yaml (kubernetes)

Tests: 94 (SUCCESSES: 80, FAILURES: 14, EXCEPTIONS: 0)
Failures: 14 (UNKNOWN: 0, LOW: 9, MEDIUM: 4, HIGH: 1, CRITICAL: 0)

# Very good, kube bench would flag the same thing
MEDIUM: Container 'nginx' of Deployment 'nginx' should set 'securityContext.allowPrivilegeEscalation' to false
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
A program inside the container can elevate its own privileges and run as root, which might give the program control over the container and node.

See https://avd.aquasec.com/misconfig/ksv001
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
deployment.yaml:21-23
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
21 β”Œ - image: nginx
22 β”‚ name: nginx
23 β”” resources: {}
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

# Great, kube bench would also flag this.
LOW: Container 'nginx' of Deployment 'nginx' should add 'ALL' to 'securityContext.capabilities.drop'
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
The container should drop all default capabilities and add only those that are needed for its execution.

See https://avd.aquasec.com/misconfig/ksv003
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
deployment.yaml:21-23
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
21 β”Œ - image: nginx
22 β”‚ name: nginx
23 β”” resources: {}
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

# Really missing limits on this container
LOW: Container 'nginx' of Deployment 'nginx' should set 'resources.limits.cpu'
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
Enforcing CPU limits prevents DoS via resource exhaustion.

See https://avd.aquasec.com/misconfig/ksv011
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
deployment.yaml:21-23
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
21 β”Œ - image: nginx
22 β”‚ name: nginx
23 β”” resources: {}
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

# Would also be flagged by kube bench
MEDIUM: Container 'nginx' of Deployment 'nginx' should set 'securityContext.runAsNonRoot' to true
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
Force the running image to run as a non-root user to ensure least privileges.

See https://avd.aquasec.com/misconfig/ksv012
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
deployment.yaml:21-23
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
21 β”Œ - image: nginx
22 β”‚ name: nginx
23 β”” resources: {}
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

# Perfect, because we shouldn't run with the latest tag
MEDIUM: Container 'nginx' of Deployment 'nginx' should specify an image tag
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
It is best to avoid using the ':latest' image tag when deploying containers in production. Doing so makes it hard to track which version of the image is running, and hard to roll back the version.

See https://avd.aquasec.com/misconfig/ksv013
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
deployment.yaml:21-23
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
21 β”Œ - image: nginx
22 β”‚ name: nginx
23 β”” resources: {}
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

# Would also flag in kube bench
HIGH: Container 'nginx' of Deployment 'nginx' should set 'securityContext.readOnlyRootFilesystem' to true
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
An immutable root file system prevents applications from writing to their local disk. This can limit intrusions, as attackers will not be able to tamper with the file system or write foreign executables to disk.

See https://avd.aquasec.com/misconfig/ksv014
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
deployment.yaml:21-23
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
21 β”Œ - image: nginx
22 β”‚ name: nginx
23 β”” resources: {}
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

# Same situation as limits above, but for cpu and memory requests
LOW: Container 'nginx' of Deployment 'nginx' should set 'resources.requests.cpu'
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
When containers have resource requests specified, the scheduler can make better decisions about which nodes to place pods on, and how to deal with resource contention.

See https://avd.aquasec.com/misconfig/ksv015
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
deployment.yaml:21-23
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
21 β”Œ - image: nginx
22 β”‚ name: nginx
23 β”” resources: {}
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────


LOW: Container 'nginx' of Deployment 'nginx' should set 'resources.requests.memory'
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
When containers have memory requests specified, the scheduler can make better decisions about which nodes to place pods on, and how to deal with resource contention.

See https://avd.aquasec.com/misconfig/ksv016
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
deployment.yaml:21-23
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
21 β”Œ - image: nginx
22 β”‚ name: nginx
23 β”” resources: {}
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────


LOW: Container 'nginx' of Deployment 'nginx' should set 'resources.limits.memory'
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
Enforcing memory limits prevents DoS via resource exhaustion.

See https://avd.aquasec.com/misconfig/ksv018
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
deployment.yaml:21-23
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
21 β”Œ - image: nginx
22 β”‚ name: nginx
23 β”” resources: {}
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

# Same as kube-bench, which also asks to put user and group above 10000. I'm starting to think trivy has kube bench embedded.
LOW: Container 'nginx' of Deployment 'nginx' should set 'securityContext.runAsUser' > 10000
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
Force the container to run with user ID > 10000 to avoid conflicts with the host's user table.

See https://avd.aquasec.com/misconfig/ksv020
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
deployment.yaml:21-23
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
21 β”Œ - image: nginx
22 β”‚ name: nginx
23 β”” resources: {}
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────


LOW: Container 'nginx' of Deployment 'nginx' should set 'securityContext.runAsGroup' > 10000
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
Force the container to run with group ID > 10000 to avoid conflicts with the host's user table.

See https://avd.aquasec.com/misconfig/ksv021
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
deployment.yaml:21-23
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
21 β”Œ - image: nginx
22 β”‚ name: nginx
23 β”” resources: {}
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────


LOW: Either Pod or Container should set 'securityContext.seccompProfile.type' to 'RuntimeDefault'
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
According to pod security standard 'Seccomp', the RuntimeDefault seccomp profile must be required, or allow specific additional profiles.

See https://avd.aquasec.com/misconfig/ksv030
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
deployment.yaml:21-23
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
21 β”Œ - image: nginx
22 β”‚ name: nginx
23 β”” resources: {}
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────


MEDIUM: container "nginx" of deployment "nginx" in "default" namespace should specify a seccomp profile
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
A program inside the container can bypass Seccomp protection policies.

See https://avd.aquasec.com/misconfig/ksv104
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────


LOW: container should drop all
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
Containers must drop ALL capabilities, and are only permitted to add back the NET_BIND_SERVICE capability.

See https://avd.aquasec.com/misconfig/ksv106
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
deployment.yaml:21-23
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
21 β”Œ - image: nginx
22 β”‚ name: nginx
23 β”” resources: {}
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Well, we saw that trivy also does a good job with IaC declarative files. And a helm will it work?

helm repo add aqua https://aquasecurity.github.io/helm-charts/
helm pull aqua/trivy --untar

trivy config trivy
2024-09-03T23:45:45-03:00 INFO [misconfig] Misconfiguration scanning is enabled
2024-09-03T23:45:46-03:00 INFO Detected config files num=7

# Files found...
templates/statefulset.yaml (helm)

Tests: 94 (SUCCESSES: 87, FAILURES: 7, EXCEPTIONS: 0)
Failures: 7 (UNKNOWN: 0, LOW: 5, MEDIUM: 2, HIGH: 0, CRITICAL: 0)

MEDIUM: Container 'main' of StatefulSet 'trivy' should set 'securityContext.allowPrivilegeEscalation' to false
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
A program inside the container can elevate its own privileges and run as root, which might give the program control over the container and node.

See https://avd.aquasec.com/misconfig/ksv001
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
templates/statefulset.yaml:45-92
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
45 β”Œ - name: main
46 β”‚ image: docker.io/aquasec/trivy:0.37.2
47 β”‚ imagePullPolicy: "IfNotPresent"
48 β”‚ securityContext:
49 β”‚ privileged: false
50 β”‚ readOnlyRootFilesystem: true
51 β”‚ args:
52 β”‚ - server
53 β”” envFrom:
..
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────


LOW: Container 'main' of StatefulSet 'trivy' should add 'ALL' to 'securityContext.capabilities.drop'
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
The container should drop all default capabilities and add only those that are needed for its execution.

See https://avd.aquasec.com/misconfig/ksv003
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
templates/statefulset.yaml:45-92
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
45 β”Œ - name: main
46 β”‚ image: docker.io/aquasec/trivy:0.37.2
47 β”‚ imagePullPolicy: "IfNotPresent"
48 β”‚ securityContext:
49 β”‚ privileged: false
50 β”‚ readOnlyRootFilesystem: true
51 β”‚ args:
52 β”‚ - server
53 β”” envFrom:
..
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────


LOW: Container 'main' of StatefulSet 'trivy' should set 'securityContext.runAsUser' > 10000
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
Force the container to run with user ID > 10000 to avoid conflicts with the host's user table.

See https://avd.aquasec.com/misconfig/ksv020
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
templates/statefulset.yaml:45-92
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
45 β”Œ - name: main
46 β”‚ image: docker.io/aquasec/trivy:0.37.2
47 β”‚ imagePullPolicy: "IfNotPresent"
48 β”‚ securityContext:
49 β”‚ privileged: false
50 β”‚ readOnlyRootFilesystem: true
51 β”‚ args:
52 β”‚ - server
53 β”” envFrom:
..
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────


LOW: Container 'main' of StatefulSet 'trivy' should set 'securityContext.runAsGroup' > 10000
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
Force the container to run with group ID > 10000 to avoid conflicts with the host's user table.

See https://avd.aquasec.com/misconfig/ksv021
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
templates/statefulset.yaml:45-92
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
45 β”Œ - name: main
46 β”‚ image: docker.io/aquasec/trivy:0.37.2
47 β”‚ imagePullPolicy: "IfNotPresent"
48 β”‚ securityContext:
49 β”‚ privileged: false
50 β”‚ readOnlyRootFilesystem: true
51 β”‚ args:
52 β”‚ - server
53 β”” envFrom:
..
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────


LOW: Either Pod or Container should set 'securityContext.seccompProfile.type' to 'RuntimeDefault'
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
According to pod security standard 'Seccomp', the RuntimeDefault seccomp profile must be required, or allow specific additional profiles.

See https://avd.aquasec.com/misconfig/ksv030
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
templates/statefulset.yaml:45-92
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
45 β”Œ - name: main
46 β”‚ image: docker.io/aquasec/trivy:0.37.2
47 β”‚ imagePullPolicy: "IfNotPresent"
48 β”‚ securityContext:
49 β”‚ privileged: false
50 β”‚ readOnlyRootFilesystem: true
51 β”‚ args:
52 β”‚ - server
53 β”” envFrom:
..
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────


MEDIUM: container "main" of statefulset "trivy" in "default" namespace should specify a seccomp profile
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
A program inside the container can bypass Seccomp protection policies.

See https://avd.aquasec.com/misconfig/ksv104
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────


LOW: container should drop all
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
Containers must drop ALL capabilities, and are only permitted to add back the NET_BIND_SERVICE capability.

See https://avd.aquasec.com/misconfig/ksv106
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
templates/statefulset.yaml:45-92
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
45 β”Œ - name: main
46 β”‚ image: docker.io/aquasec/trivy:0.37.2
47 β”‚ imagePullPolicy: "IfNotPresent"
48 β”‚ securityContext:
49 β”‚ privileged: false
50 β”‚ readOnlyRootFilesystem: true
51 β”‚ args:
52 β”‚ - server
53 β”” envFrom:
..

FS Analysis​

It's not necessary to create the application image to check the project you're working on. Obviously after we build the image we'll have an inheritance from the chosen base, but we can just check the project itself.

trivy fs <path to project directory>

In this example I'll scan the docusaurus project itself, the very one I'm writing.

# I only passed what I want to scan to not pick up secrets that are in the project which are examples.

❯ trivy fs . --scanners vuln,misconfig
2024-09-04T09:36:23-03:00 INFO [vuln] Vulnerability scanning is enabled
2024-09-04T09:36:23-03:00 INFO [misconfig] Misconfiguration scanning is enabled
2024-09-04T09:36:26-03:00 INFO Number of language-specific files num=1
2024-09-04T09:36:26-03:00 INFO [npm] Detecting vulnerabilities...
2024-09-04T09:36:26-03:00 INFO Detected config files num=3

node_modules/@surma/rollup-plugin-off-main-thread/Dockerfile (dockerfile)

Tests: 27 (SUCCESSES: 23, FAILURES: 4, EXCEPTIONS: 0)
Failures: 4 (UNKNOWN: 0, LOW: 1, MEDIUM: 1, HIGH: 2, CRITICAL: 0)

MEDIUM: Specify a tag in the 'FROM' statement for image 'selenium/node-chrome'
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
When using a 'FROM' statement you should use a specific tag to avoid uncontrolled behavior when the image is updated.

See https://avd.aquasec.com/misconfig/ds001
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
node_modules/@surma/rollup-plugin-off-main-thread/Dockerfile:1
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 [ FROM selenium/node-chrome:latest
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────


HIGH: Last USER command in Dockerfile should not be 'root'
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
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.

See https://avd.aquasec.com/misconfig/ds002
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
node_modules/@surma/rollup-plugin-off-main-thread/Dockerfile:3
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
3 [ USER root
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────


HIGH: The instruction 'RUN <package-manager> update' should always be followed by '<package-manager> install' in the same RUN statement.
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
The instruction 'RUN <package-manager> update' should always be followed by '<package-manager> install' in the same RUN statement.

See https://avd.aquasec.com/misconfig/ds017
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
node_modules/@surma/rollup-plugin-off-main-thread/Dockerfile:5-8
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
5 β”Œ RUN apt-get update -qqy \
6 β”‚ && rm -rf /var/lib/apt/lists/* /var/cache/apt/* \
7 β”‚ && rm /bin/sh && ln -s /bin/bash /bin/sh \
8 β”” && chown seluser /usr/local
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────


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
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

# We can also check licenses
trivy fs . --scanners license

Local scanning allows evaluating modules that are installed while building the project. Unlike if we scan a repository where we ignore using .gitignore several build files.

It's also useful to enter a container and do internal analysis.

Repository Analysis​

If we do the same analysis above, we can observe that we won't have node_modules, because it won't be in the repository.

Note that the analyses are looking at package versions and not the binaries.

❯ trivy repository https://gitlab.com/davidpuziol/devsecops.git --scanners vulnerability,misconfig
2024-09-04T09:47:14-03:00 INFO [vuln] Vulnerability scanning is enabled
2024-09-04T09:47:14-03:00 INFO [misconfig] Misconfiguration scanning is enabled
Enumerating objects: 1371, done.
Counting objects: 100% (1371/1371), done.
Compressing objects: 100% (1281/1281), done.
Total 1371 (delta 32), reused 1166 (delta 28), pack-reused 0 (from 0)
2024-09-04T09:47:21-03:00 INFO [npm] To collect the license information of packages, "npm install" needs to be performed beforehand dir="node_modules"
2024-09-04T09:47:22-03:00 INFO Number of language-specific files num=1
2024-09-04T09:47:22-03:00 INFO [npm] Detecting vulnerabilities...
2024-09-04T09:47:22-03:00 INFO Detected config files num=2

package-lock.json (npm)

Total: 2 (UNKNOWN: 0, LOW: 0, MEDIUM: 2, HIGH: 0, CRITICAL: 0)

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Library β”‚ Vulnerability β”‚ Severity β”‚ Status β”‚ Installed Version β”‚ Fixed Version β”‚ Title β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ micromatch β”‚ CVE-2024-4067 β”‚ MEDIUM β”‚ fixed β”‚ 4.0.5 β”‚ 4.0.8 β”‚ micromatch: vulnerable to Regular Expression Denial of β”‚
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ Service β”‚
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2024-4067 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ webpack β”‚ CVE-2024-43788 β”‚ β”‚ β”‚ 5.91.0 β”‚ 5.94.0 β”‚ webpack: DOM Clobbering vulnerability in β”‚
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ AutoPublicPathRuntimeModule β”‚
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2024-43788 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜