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:

  • Container images (Docker, OCI) for OS package and application-dependency vulnerabilities.
  • Filesystems and local directories for the same, plus embedded secrets.
  • Git repositories (remote or local) for vulnerabilities and misconfigurations.
  • Infrastructure-as-Code files (Terraform, CloudFormation, Kubernetes manifests, Dockerfiles, Helm charts) for misconfigurations.
  • Kubernetes clusters directly, scanning live workloads.
  • SBOMs (Software Bill of Materials) in CycloneDX and SPDX formats, both generating and scanning them.
  • License information for dependencies.
  • Secrets such as API keys, tokens, and private keys accidentally baked into images or code.

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

  • CI/CD pipeline gating – fail a build if CRITICAL vulnerabilities without a fix are found.
  • Registry scanning – periodically scan every image in a private registry for drift.
  • Pre-deployment gate – scan Kubernetes manifests/Helm charts with trivy config before kubectl apply.
  • Supply-chain auditing – generate SBOMs for every release artifact and archive them for compliance.
  • Secret leak detection – scan repositories and images before publishing to catch hard-coded credentials.
  • Compliance reporting – run --compliance docker-cis or k8s-cis reports for auditors.

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

  • Run trivy image --download-db-only on a schedule (cron) so scans stay fast and offline-capable.
  • Always combine --ignore-unfixed with CI gating — blocking builds for vulnerabilities with no available fix creates noise without actionable remediation.
  • Use --scanners vuln,misconfig,secret together on fs/repository targets for full-spectrum coverage in one pass.
  • Store .trivyignore files in version control with comments explaining why each CVE is suppressed, and set expiry review dates.
  • In air-gapped environments, mirror the vulnerability DB using trivy --cache-dir and oras/skopeo to move the OCI DB artifact.
  • Prefer --format json piped to jq for machine-parseable pipeline decisions rather than parsing table output.
  • Pin the Trivy version in CI to avoid unexpected new checks silently breaking existing pipelines.

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

  • Official documentation: https://aquasecurity.github.io/trivy/
  • GitHub repository: https://github.com/aquasecurity/trivy
  • Vulnerability DB source: https://github.com/aquasecurity/trivy-db
  • Aqua Security blog: https://www.aquasec.com/blog/
Total
0
Shares

Leave a Reply

Previous Post
S3Scanner: Complete Guide to Amazon S3 Bucket Discovery and Security Assessment Using Kali Linux

S3Scanner: Complete Guide to Amazon S3 Bucket Discovery and Security Assessment Using Kali Linux

Next Post
Docker Bench: Complete Guide to Docker Security Auditing and CIS Benchmark Assessment Using Kali Linux

Docker Bench: Complete Guide to Docker Security Auditing and CIS Benchmark Assessment Using Kali Linux

Related Posts