By Manny Fernandez

October 8, 2026

Trivy on macOS: Install It, Verify It, Run It

What Trivy Is and Why You Want It

Trivy is Aqua Security’s open source, all-in-one scanner: one binary that finds CVEs, misconfigurations, exposed secrets, and license issues across container images, local filesystems, git repos, IaC templates, SBOMs, and Kubernetes clusters. It runs locally against a vulnerability database it downloads and caches for you, so there is no server to stand up and no account to create.

The current release is v0.74.0, published August 14, 2026 (releases). This guide gets it installed on macOS the safe way, then walks through the scans you will actually run day to day.

Target audience: practitioners on macOS (Apple Silicon or Intel) who want a working scanner in about ten minutes.

Prerequisites

You need a recent macOS with Homebrew and outbound HTTPS to GitHub and the GitHub Container Registry, where Trivy pulls its vulnerability DB.

Component Requirement Check with
macOS Apple Silicon or Intel, currently supported release sw_vers
Homebrew Installed and updated brew --version
Docker Desktop, OrbStack, or Colima Only for scanning local images you built docker info
cosign Only if you install the release binary manually cosign version
Network HTTPS to github.com, ghcr.io, mirror.gcr.io curl -I https://ghcr.io

No container runtime is required to scan remote registry images. Trivy pulls the layers itself.

Installing Trivy on macOS

Use the official Homebrew core formula. It builds Trivy from source instead of pulling a prebuilt release binary, which is why it was not affected by the March 2026 compromise (next section).

Option 1: Homebrew core formula (recommended)

Goal: a managed install that updates with the rest of your brew packages.

brew update
brew install trivy

Verify:

which trivy
trivy --version

Expected: a path under /opt/homebrew/bin (Apple Silicon) or /usr/local/bin (Intel), and Version: 0.74.0 or newer.

Avoid brew install aquasecurity/trivy/trivy. That custom tap is not the core formula, and it shipped the malicious build during the March incident. If you have it, remove it:

brew uninstall aquasecurity/trivy/trivy 2>/dev/null
brew untap aquasecurity/trivy 2>/dev/null
brew install trivy

Option 2: Signed release binary

Goal: a pinned version you verify yourself, useful for air-gapped jump boxes or pinned CI runners.

VER=0.74.0
ARCH=macOS-ARM64   # use macOS-64bit on Intel
BASE=https://github.com/aquasecurity/trivy/releases/download/v${VER}

curl -sLO "${BASE}/trivy_${VER}_${ARCH}.tar.gz"
curl -sLO "${BASE}/trivy_${VER}_${ARCH}.tar.gz.sigstore.json"

brew install cosign
cosign verify-blob \
  --certificate-identity-regexp 'https://github\.com/aquasecurity/' \
  --certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
  --bundle "trivy_${VER}_${ARCH}.tar.gz.sigstore.json" \
  "trivy_${VER}_${ARCH}.tar.gz"

Expected: Verified OK. Then extract and place it on your PATH:

tar -xzf "trivy_${VER}_${ARCH}.tar.gz" trivy
sudo install -m 0755 trivy /usr/local/bin/trivy
trivy --version

If Gatekeeper blocks the first run, clear the quarantine flag on the binary you just verified: xattr -d com.apple.quarantine /usr/local/bin/trivy.

Option 3: Run it in a container

Goal: zero install footprint on the Mac itself. Pin the tag and mount a cache so the DB is not re-downloaded every run.

docker run --rm \
  -v "$HOME/Library/Caches/trivy:/root/.cache/" \
  aquasec/trivy:0.74.0 image nginx:1.27

Never use :latest for a security tool. Pin the version, and verify the image with cosign verify aquasec/trivy:0.74.0 using the same identity and issuer flags as above.

The March 2026 Incident: Check Your Install

On March 19, 2026, attackers used stolen CI credentials to publish a malicious Trivy v0.69.4 release and hijack the trivy-action and setup-trivy GitHub Actions with a credential stealer (GHSA-69fq-xp46-6×23). The irony writes itself: the scanner became the supply-chain attack.

Artifact Affected Notes
Release binary v0.69.4 Yes Live for roughly 3 hours
Docker Hub aquasec/trivy:0.69.4, 0.69.5, 0.69.6 Yes 0.69.5 and 0.69.6 confirmed March 22 (StepSecurity)
aquasecurity/trivy custom Homebrew tap Yes Not the documented install path
Homebrew core brew install trivy No Builds from source
trivy-action tags 0.0.1 to 0.34.2 Yes, March 19 to 20 Pin actions to full commit SHAs

If any Mac or runner touched an affected artifact in that window, treat its credentials (cloud keys, SSH keys, registry tokens, ~/.docker/config.json) as exposed and rotate them.

Quick self-check on your Mac:

trivy --version
brew info trivy | head -n 3
brew tap | grep -i aquasecurity || echo "no aquasecurity tap"

You want a version of 0.74.0 or newer, installed from homebrew/core, and no aquasecurity tap.

One honest limit: cosign proves a binary came from Aqua’s CI, not that Aqua’s CI was uncompromised. The v0.69.4 build was legitimately signed. Pinning known-good versions and not auto-grabbing brand-new releases on day zero is what actually buys you margin.

Your First Scan: A Container Image

The first run downloads the vulnerability DB (a few hundred MB) into ~/Library/Caches/trivy, so expect it to take a minute. Every run after that is fast.

trivy image nginx:1.27

Trivy detects the base OS, inventories OS packages and language libraries, and prints a table per target. Abbreviated output:

nginx:1.27 (debian 12.x)
========================
Total: 143 (UNKNOWN: 0, LOW: 82, MEDIUM: 43, HIGH: 14, CRITICAL: 4)

| Library | Vulnerability  | Severity | Status | Installed | Fixed |
|---------|----------------|----------|--------|-----------|-------|
| libssl3 | CVE-2025-XXXXX | CRITICAL | fixed  | 3.0.x     | 3.0.y |

How to read it:

  • Status fixed means an upstream patch exists. Rebuild or bump the base image and it goes away.
  • Status affected or will_not_fix means no fix is available yet. Track it, accept it, or change base images.
  • Installed vs. Fixed tells you exactly which package version to move to.

To scan an image you built locally, Trivy reads it straight from Docker, OrbStack, or Podman. No push needed:

docker build -t myapp:dev .
trivy image myapp:dev

Private registries use your existing docker login credentials automatically.

Beyond Images: The Other Targets

Same binary, same flags, different subcommand. The --scanners flag picks what to look for: vuln, misconfig, secret, license.

Filesystem or project directory

Scans lockfiles (package-lock.json, go.sum, requirements.txt, Gemfile.lock, Cargo.lock, and more) plus hardcoded secrets.

trivy fs --scanners vuln,secret,misconfig .

Remote git repository

trivy repo https://github.com/<org>/<repo>

Infrastructure as code

Checks Terraform, CloudFormation, Kubernetes YAML, Helm charts, and Dockerfiles against built-in policies (root user, open security groups, missing encryption).

trivy config ./terraform
trivy config Dockerfile

Generate and rescan an SBOM

Generate once at build time, then rescan against tomorrow’s DB without rebuilding anything.

trivy image --format cyclonedx -o sbom.cdx.json myapp:dev
trivy sbom sbom.cdx.json

Kubernetes cluster

Uses your current kubectl context. Start with the summary report.

trivy k8s --report summary

Your Mac’s own dev tooling

A quick win: point fs at a project folder full of cloned tools to catch vulnerable dependencies you forgot you had.

trivy fs --scanners vuln --severity HIGH,CRITICAL ~/Projects

Cutting the Noise: Filters, Formats, and Exit Codes

A raw scan of a full Debian image returns hundreds of findings. These flags turn that into something actionable.

Flag What it does
--severity HIGH,CRITICAL Only report these severities
--ignore-unfixed Hide findings with no available fix
--exit-code 1 Return non-zero when findings match, for CI gating
--pkg-types os or library Limit to OS packages or app dependencies
--ignorefile .trivyignore Suppress accepted CVE IDs, one per line
--format json / sarif / cyclonedx / spdx-json Machine-readable output
-o <file> Write output to a file
--skip-dirs, --skip-files Exclude paths such as node_modules or test fixtures

The CI gate one-liner

Fail the build only on fixable HIGH or CRITICAL issues:

trivy image --severity HIGH,CRITICAL --ignore-unfixed \
  --exit-code 1 myapp:dev
echo "exit: $?"

Expected: exit: 0 on a clean image, exit: 1 when something fixable and serious is present.

Documenting accepted risk

Keep a .trivyignore in the repo so exceptions are reviewed in pull requests, not hidden in pipeline config:

# Not reachable: we do not use the affected module. Review by 2026-12-31.
CVE-2025-12345

Reports for humans

trivy image --format json -o report.json myapp:dev
trivy image --format sarif -o report.sarif myapp:dev

SARIF drops straight into GitHub code scanning. JSON feeds anything else.

If you run Trivy in GitHub Actions, pin aquasecurity/trivy-action to a full commit SHA, never a version tag. Tags are mutable, and that is exactly how the March attack spread.

Keeping Trivy and Its Database Current

There are two things to keep fresh: the binary and the vulnerability DB. The DB is rebuilt every six hours upstream, and Trivy refreshes it automatically when your local copy is stale.

# Binary
brew upgrade trivy

# Force a DB refresh without scanning anything
trivy image --download-db-only

# Where the cache lives, and how big it is
du -sh ~/Library/Caches/trivy

# Wipe scan cache and DBs, then let the next scan re-download
trivy clean --all

For offline or rate-limited environments, scan with the DB you already have:

trivy image --skip-db-update myapp:dev

Troubleshooting and Gotchas

1. DB download fails with TOOMANYREQUESTS or times out. GHCR rate-limits anonymous pulls, and corporate proxies with SSL inspection break the download. Point Trivy at an alternate DB repository, and export your proxy variables if you sit behind one.

trivy image --db-repository mirror.gcr.io/aquasec/trivy-db myapp:dev
export HTTPS_PROXY=http://proxy.example.local:8080

If a FortiGate or other NGFW is doing deep inspection, either exempt ghcr.io and mirror.gcr.io or trust the inspection CA in the macOS keychain.

2. unable to inspect the image on a local build. Trivy cannot find your container runtime’s socket. OrbStack and Colima use non-default socket paths.

docker context ls
export DOCKER_HOST=$(docker context inspect \
  --format '{{.Endpoints.docker.Host}}')
trivy image myapp:dev

3. trivy: command not found after install. Homebrew’s bin directory is not on your PATH, which is common on a fresh Apple Silicon Mac.

echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile
source ~/.zprofile

4. Findings look wildly different between two machines. One of them has a stale DB or an old binary. Compare trivy --version output on both, which also prints the DB version and its update timestamp.

Quick Reference

Task Command
Install brew install trivy
Upgrade brew upgrade trivy
Version and DB age trivy --version
Scan an image trivy image nginx:1.27
Scan a project folder trivy fs --scanners vuln,secret,misconfig .
Scan a remote repo trivy repo https://github.com/<org>/<repo>
Scan IaC trivy config ./terraform
Make an SBOM trivy image --format cyclonedx -o sbom.cdx.json <image>
Rescan an SBOM trivy sbom sbom.cdx.json
Cluster summary trivy k8s --report summary
CI gate trivy image --severity HIGH,CRITICAL --ignore-unfixed --exit-code 1 <image>
Refresh DB only trivy image --download-db-only
Clear cache trivy clean --all

Sources

Recent posts

  • If you've spent any time configuring user authentication on... Full Story

  • DNS is one of those technologies that quietly underpins... Full Story

  • BGP issues on FortiGate firewalls usually trace back to... Full Story

  • Every time your laptop talks to your router, a... Full Story

  • If you've spent any time configuring NAT on a... Full Story

  • If you have spent any time configuring firewall policies... Full Story

  • High availability on FortiGate is one of those features... Full Story

  • If you've configured SD-WAN on a FortiGate, you've almost... Full Story

  • FortiLink is the management protocol that turns a FortiSwitch... Full Story

  • FortiSwitches are pretty rock solid from Mean Time Between... Full Story

  • This is a quicky tip.  Have you ever gone... Full Story

  • DNS is one of those quiet pieces of internet... Full Story

  • This article is an updated version of the previous... Full Story

  • You will add ns2 as a secondary (slave) BIND9... Full Story

  • In the process of deploying my lab, I needed... Full Story

  • RFC 8805, used to be known as Self-Correcting IP... Full Story

  • Years back, I wrote an article about certificate pinning. ... Full Story

  • FortiGates have the ability to send alerts to Microsoft... Full Story

  • In this post, I am going to walk through... Full Story

  • Troubleshooting VoIP on a FortiGate can feel like trying... Full Story

  • Prior to FortiOS 7.0, there were three commands to... Full Story

  • In this post, I am going to go over... Full Story

  • What we are going to do:  We are going... Full Story

  • Choosing between FGCP (FortiGate Clustering Protocol) and FGSP (FortiGate... Full Story

  • Creating a VLAN on macOS (The "Pro" Move) A... Full Story

  • This blog post explores the logic behind how macOS... Full Story

  • Pretty Fly for a Wi-Fi Tell My Wi-Fi Love... Full Story

  • Part of my daily gig is creating BoMs (Bill-of-Materials)... Full Story

  • ICMP introduces several security risks, but careful filtering, rate... Full Story

  • The command diag debug application dhcps -1 enables full... Full Story

  • In the world of FortiOS, execute tac report is... Full Story

  • LLDP; What is it The Link Layer Discovery Protocol... Full Story

  • What it actually does When you run diagnose fdsm... Full Story

  • Monkey Bites are bite-sized, high-impact security insights designed for... Full Story

  • I have run macOS in macOS with Parallels but... Full Story

  • Don't be confused with my other FortiNAC posts where... Full Story

  • This is the third session in a multi-part article... Full Story

  • Today I was configuring key-based authentication on a FortiGate... Full Story

  • Netcat, often called the "Swiss Army knife" of networking,... Full Story

  • At its core, IEEE 802.1X is a network layer... Full Story

  • In case you did not see the previous FortiNAC... Full Story

  • This is our 5th session where we are going... Full Story

  • Now that we have Wireshark installed and somewhat configured,... Full Story

  • The Philosophy of Packet Analysis Troubleshooting isn't about looking... Full Story

  • Executive Summary Objective: Give you a working command of... Full Story

  • You have configured it a dozen times. Server IP,... Full Story

  • Executive Summary Objective: Walk through every message a FortiGate... Full Story