Trivy: Complete Guide to Container, Kubernetes, and Vulnerability Scanning Using Kali Linux

Trivy: Complete Guide to Container, Kubernetes, and Vulnerability Scanning Using Kali Linux

Trivy (pronounced “tri-vee”, short for “Triple Vee” / vulnerability, misconfiguration, secret) is an open-source, all-in-one security scanner developed by Aqua Security. It is one of the most widely adopted container and software supply-chain security tools because a single binary can scan:

Trivy is fast because it caches vulnerability databases locally and uses efficient layer analysis, and it is accurate because it pulls from multiple upstream vulnerability sources (NVD, GitHub Security Advisories, distro-specific advisories such as Debian DSA, Red Hat OVAL, Alpine SecDB, etc.).

Installation

Method 1 – APT repository (recommended for Kali/Debian-based systems):

sudo apt-get install wget apt-transport-https gnupg lsb-release -y
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | sudo gpg --dearmor -o /usr/share/keyrings/trivy.gpg
echo "deb [signed-by=/usr/share/keyrings/trivy.gpg] https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main" | sudo tee -a /etc/apt/sources.list.d/trivy.list
sudo apt-get update
sudo apt-get install trivy -y

Method 2 – Install script:

curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sudo sh -s -- -b /usr/local/bin

Method 3 – Binary download from GitHub releases:

wget https://github.com/aquasecurity/trivy/releases/download/v0.55.2/trivy_0.55.2_Linux-64bit.deb
sudo dpkg -i trivy_0.55.2_Linux-64bit.deb

Method 4 – Docker (no local install):

docker run --rm -v /var/run/docker.sock:/var/run/docker.sock aquasec/trivy image alpine:3.19

Verify installation:

trivy --version

Expected output:

Version: 0.55.2
Vulnerability DB:
  Version: 2
  UpdatedAt: 2026-07-18 06:12:31.123456789 +0000 UTC
  NextUpdate: 2026-07-19 06:12:31.123456789 +0000 UTC
  DownloadedAt: 2026-07-18 09:04:11.987654321 +0000 UTC

Syntax

trivy [global options] command [command options] [target]

General command form:

trivy <SCAN_TYPE> [FLAGS] <TARGET>

Where <SCAN_TYPE> is one of: image, fs, rootfs, repository, kubernetes, sbom, config, secret, vm, plugin.

Command-Line Options (Full Reference)

Top-level commands:

CommandPurpose
trivy imageScan a container image
trivy fsScan a filesystem/directory
trivy rootfsScan a mounted root filesystem
trivy repositoryScan a remote/local Git repository
trivy kubernetesScan a live Kubernetes cluster
trivy configScan IaC config files for misconfigurations
trivy sbomScan an existing SBOM file
trivy vmScan a virtual machine image
trivy pluginManage Trivy plugins
trivy serverRun Trivy in client/server mode
trivy moduleManage Trivy modules
trivy cleanRemove cached data

Global flags:

FlagDescription
-q, --quietSuppress non-essential output
-d, --debugEnable debug logging
--cache-dirSet cache directory path
--configSpecify a config file (trivy.yaml)
-v, --versionPrint version
-h, --helpShow help
--timeoutSet scan timeout (default 5m)
--insecureAllow insecure server connections

Scan-specific flags (apply to image, fs, repository, etc.):

FlagDescription
--severityFilter by severity: UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL
--vuln-typeFilter: os, library, or both
--scannersChoose scanners: vuln, misconfig, secret, license
--format, -fOutput format: table, json, sarif, cyclonedx, spdx, spdx-json, github, template
--output, -oWrite results to a file
--exit-codeExit code to use when vulnerabilities found (e.g. 1)
--ignore-unfixedSkip vulnerabilities without a known fix
--ignorefilePath to .trivyignore file
--skip-dirsComma-separated dirs to skip
--skip-filesComma-separated files to skip
--no-progressSuppress progress bar
--offline-scanScan without contacting external servers
--list-all-pkgsList all packages, not just vulnerable ones
--inputScan a .tar image saved with docker save
--platformSpecify platform for multi-arch images (e.g. linux/arm64)
--db-repositoryCustom vulnerability DB OCI repository
--skip-db-updateSkip vuln DB update before scanning
--resetRemove cache and DB, then re-download
--username / --passwordRegistry credentials
--secret-configCustom path for secret detection rules
--complianceRun a compliance report (e.g. docker-cis, k8s-cis)

trivy k8s specific flags:

FlagDescription
--reportsummary or all
--namespaceScan specific namespace only
--kubeconfigPath to kubeconfig file
--include-namespacesComma-separated list to include
--exclude-namespacesComma-separated list to exclude
--compliancee.g. k8s-cis, k8s-nsa, k8s-pss-baseline, k8s-pss-restricted

Basic Usage

Scan a public image with default settings:

trivy image nginx:1.25

Expected output (truncated):

2026-07-19T10:02:11.001+0500 INFO  Vulnerability scanning is enabled
2026-07-19T10:02:11.002+0500 INFO  Detected OS: debian
2026-07-19T10:02:11.003+0500 INFO  Detecting Debian vulnerabilities...
2026-07-19T10:02:12.512+0500 INFO  Number of language-specific files: 1

nginx:1.25 (debian 12.5)
=========================
Total: 84 (UNKNOWN: 0, LOW: 40, MEDIUM: 22, HIGH: 18, CRITICAL: 4)

┌───────────────┬────────────────┬──────────┬────────┬───────────────────┬───────────────┬──────────────────────────────────────────┐
│    Library    │ Vulnerability  │ Severity │ Status │ Installed Version │ Fixed Version │                   Title                    │
├───────────────┼────────────────┼──────────┼────────┼───────────────────┼───────────────┼──────────────────────────────────────────┤
│ libssl3       │ CVE-2024-0727  │ CRITICAL │ fixed  │ 3.0.11-1~deb12u2  │ 3.0.13-1      │ openssl: PKCS12 Decoding crashes          │
│ libc-bin      │ CVE-2023-4911  │ HIGH     │ fixed  │ 2.36-9            │ 2.36-9+deb12u3│ glibc: buffer overflow in ld.so           │
└───────────────┴────────────────┴──────────┴────────┴───────────────────┴───────────────┴──────────────────────────────────────────┘

Practical Examples with Output

Example 1 – Scan and show only HIGH/CRITICAL severities:

trivy image --severity HIGH,CRITICAL alpine:3.18
alpine:3.18 (alpine 3.18.4)
============================
Total: 3 (HIGH: 2, CRITICAL: 1)

┌─────────┬────────────────┬──────────┬────────┬───────────────────┬───────────────┬─────────────────────────┐
│ Library │ Vulnerability  │ Severity │ Status │ Installed Version │ Fixed Version │          Title           │
├─────────┼────────────────┼──────────┼────────┼───────────────────┼───────────────┼─────────────────────────┤
│ openssl │ CVE-2024-13176 │ CRITICAL │ fixed  │ 3.1.4-r5          │ 3.1.5-r0      │ openssl: timing side-ch. │
│ busybox │ CVE-2023-42364 │ HIGH     │ fixed  │ 1.36.1-r2         │ 1.36.1-r5     │ busybox: OOB read        │
└─────────┴────────────────┴──────────┴────────┴───────────────────┴───────────────┴─────────────────────────┘

Example 2 – Scan a local Dockerfile for misconfigurations:

trivy config ./Dockerfile
./Dockerfile (dockerfile)
==========================
Tests: 24 (SUCCESSES: 20, FAILURES: 4, EXCEPTIONS: 0)
Failures: 4 (UNKNOWN: 0, LOW: 1, MEDIUM: 2, HIGH: 1, CRITICAL: 0)

DS002 (HIGH): Image user should not be 'root'
════════════════════════════════════════════
Last USER should not be root
────────────────────────────────────────────
 Dockerfile:1
────────────────────────────────────────────
   1 [ FROM ubuntu:22.04
────────────────────────────────────────────

Example 3 – Scan filesystem/project directory including secrets:

trivy fs --scanners vuln,secret,misconfig ./my-app
2026-07-19T10:11:04.221+0500 INFO  Number of language-specific files: 3

my-app/requirements.txt (pip)
==============================
Total: 2 (HIGH: 1, CRITICAL: 1)

my-app/.env (secrets)
======================
Total: 1 (CRITICAL: 1)

┌─────────┬───────────────────┬──────────┬─────────────────────────────────┐
│  Rule   │      Category      │ Severity │              Match               │
├─────────┼───────────────────┼──────────┼─────────────────────────────────┤
│ AWS-001 │ AWS Access Key ID │ CRITICAL │ AKIA****************             │
└─────────┴───────────────────┴──────────┴─────────────────────────────────┘

Example 4 – Scan a Git repository directly (no clone needed):

trivy repository https://github.com/example/vulnerable-app --severity CRITICAL
2026-07-19T10:14:33.100+0500 INFO  Cloning https://github.com/example/vulnerable-app...
vulnerable-app (package-lock.json)
====================================
Total: 5 (CRITICAL: 5)

Example 5 – Output results in JSON to a file:

trivy image --format json --output result.json redis:7.2
cat result.json | head -n 15
{
  "SchemaVersion": 2,
  "ArtifactName": "redis:7.2",
  "ArtifactType": "container_image",
  "Metadata": {
    "OS": {
      "Family": "debian",
      "Name": "12.5"
    }
  },
  "Results": [
    {
      "Target": "redis:7.2 (debian 12.5)",
      "Class": "os-pkgs",
      "Type": "debian"

Example 6 – Ignore vulnerabilities without a fix, exit non-zero on CRITICAL:

trivy image --ignore-unfixed --severity CRITICAL --exit-code 1 myapp:latest
echo "Exit code: $?"
myapp:latest (debian 12.5)
============================
Total: 1 (CRITICAL: 1)
...
Exit code: 1

Example 7 – Scan an offline/air-gapped tarball image:

docker save myapp:latest -o myapp.tar
trivy image --input myapp.tar
2026-07-19T10:22:01.884+0500 INFO  Loading myapp.tar
myapp.tar (alpine 3.19.1)
==========================
Total: 6 (LOW: 4, MEDIUM: 2)

Example 8 – Scan a live Kubernetes cluster namespace:

trivy kubernetes --namespace production --report summary
Summary Report for production
===============================
┌───────────┬──────────────┬────────┬─────────┬────────┬───────┬──────────┐
│ Namespace │   Resource   │ Vulns  │ Misconf │ Secret │ RBAC  │ Overall  │
├───────────┼──────────────┼────────┼─────────┼────────┼───────┼──────────┤
│production │ Deployment/web│ 14 (2C)│  3       │  0      │  -    │ FAIL     │
└───────────┴──────────────┴────────┴─────────┴────────┴───────┴──────────┘

Example 9 – Generate an SBOM in CycloneDX format:

trivy image --format cyclonedx --output sbom.json nginx:1.25
2026-07-19T10:27:44.301+0500 INFO  Generating CycloneDX SBOM...
2026-07-19T10:27:45.902+0500 INFO  SBOM written to sbom.json

Example 10 – Use a .trivyignore file to suppress known false positives:

cat .trivyignore
# Ignore this specific CVE - accepted risk
CVE-2023-1234
trivy image --ignorefile .trivyignore myapp:latest
myapp:latest (alpine 3.19.1)
==============================
Total: 5 (was 6, 1 ignored via .trivyignore)

Example 11 – Run a CIS Docker Compliance report:

trivy image --compliance docker-cis myapp:latest
Docker CIS 1.6.0 Compliance Report
====================================
┌────────┬───────────────────────────────┬────────┐
│  ID    │           Title                │ Status │
├────────┼───────────────────────────────┼────────┤
│ 5.6    │ Root user should not be used   │ FAIL   │
│ 5.10   │ Memory usage should be limited │ PASS   │
└────────┴───────────────────────────────┴────────┘

Example 12 – Scan multiple images in a loop and export CSV summary:

for img in nginx:1.25 redis:7.2 alpine:3.19; do
  count=$(trivy image --severity CRITICAL --format json "$img" | jq '[.Results[]?.Vulnerabilities[]?] | length')
  echo "$img,$count" >> summary.csv
done
cat summary.csv
nginx:1.25,4
redis:7.2,1
alpine:3.19,1

Common Use Cases

Automation with Bash

#!/usr/bin/env bash
# trivy-ci-gate.sh - Fail CI build on CRITICAL vulnerabilities with a fix available
set -euo pipefail

IMAGE="$1"
REPORT_DIR="./trivy-reports"
mkdir -p "$REPORT_DIR"

echo "[*] Updating Trivy DB..."
trivy image --download-db-only

echo "[*] Scanning $IMAGE ..."
trivy image \
  --severity CRITICAL,HIGH \
  --ignore-unfixed \
  --exit-code 1 \
  --format json \
  --output "$REPORT_DIR/$(echo "$IMAGE" | tr '/:' '_').json" \
  "$IMAGE"

STATUS=$?
if [ "$STATUS" -ne 0 ]; then
  echo "[!] Build blocked: CRITICAL/HIGH vulnerabilities found in $IMAGE"
  exit 1
fi
echo "[+] $IMAGE passed the security gate."

Run it:

chmod +x trivy-ci-gate.sh
./trivy-ci-gate.sh myapp:latest

Tips and Best Practices

Troubleshooting

ProblemCauseFix
unable to open GOB file cache errorCorrupted local cacheRun trivy clean --all and rescan
Scan hangs on DB downloadFirewall blocking GitHub Container RegistrySet --skip-db-update and pre-seed cache, or allow ghcr.io
permission denied scanning Docker socketUser not in docker groupsudo usermod -aG docker $USER and re-login
Rate limit errors pulling DBGitHub API rate limitingSet GITHUB_TOKEN env var to authenticate DB pulls
No vulnerabilities found on known-bad imageWrong --vuln-type filterRemove filter or set --vuln-type os,library
context deadline exceededDefault 5m timeout too short for large imagesIncrease with --timeout 15m

References

Exit mobile version