aquasecurity/trivy
Debugging
Trivy is a long pipeline (artifact → walker → analyzers → scanners → detectors → reports) that touches the network, the filesystem, container runtimes, and a couple of pre-built databases. When a scan misbehaves, narrowing the problem down quickly is mostly about turning on the right log level and finding the right cache to inspect.
Logging
Trivy uses a structured logger built on log/slog exposed through pkg/log/. The CLI honors several flags:
--debug— verbose log output (sets level to debug).--quiet— suppress info-level output.--no-progress— suppress the progress bar (useful in CI).--trace— even more detail; enables logging of internal stages and walker decisions.
In code, log with log.Info, log.Debug, log.Warn, log.Error, or log.Fatal. Use log.String("key", value), log.Int("count", n), log.Err(err) to attach structured fields:
log.Debug("Analyzed file", log.String("path", path), log.String("type", string(typ)))The logger is initialized in pkg/log/log.go. Test helpers can override it.
Tracing the scan pipeline
The most useful first step is --debug. It will show:
- Which artifact handler was selected.
- Which analyzers ran, and how many files each saw.
- Which cache hits/misses happened.
- The DB version that was loaded and its update behavior.
- For client/server: the RPC endpoint, request, and response sizes.
For very fine-grained walker behavior use --trace.
Common reproduction recipes
A vulnerability is missing. Re-run with --debug and check for the package family detector. If the OS isn't detected, pkg/scan/service.go logs OS not detected and skips OS package scanning.
A vulnerability is a false positive. Use a VEX statement to suppress it locally, then file a bug. The VEX subsystem is in pkg/vex/.
An IaC rule misfires. Run with --trace and check the parsed configuration. The Terraform parser in pkg/iac/scanners/terraform/parser/ is the largest source of edge cases; it has a parser_test.go of nearly 3,000 lines for a reason.
A secret rule misfires. Built-in rules live in pkg/fanal/secret/builtin-rules.go. To temporarily disable a rule, write a custom secret config (pkg/fanal/secret/scanner.go reads it) and pass --secret-config.
Stale cache. Trivy's cache lives at ~/.cache/trivy/ by default. Wipe it (or specific blobs) with trivy clean --all (pkg/commands/clean/).
Working with a bad image
When an image scan fails or hangs, narrow down with the lower-level debug commands:
trivy image --debug --download-db-only # only refresh the DB
trivy image --debug --skip-db-update IMAGE # don't even check for updates
trivy image --debug --image-src docker IMAGE # force the Docker daemon backend
trivy image --debug --image-src podman IMAGE # force podmanThe image source backends live in pkg/fanal/image/.
Working with the database
pkg/db/db.go shows the DB lifecycle. The DB is a bbolt file inside an OCI bundle. To inspect:
trivy --cache-dir /tmp/trivy-debug --debug --download-db-only image alpine:latest
ls /tmp/trivy-debug/db/To download a specific version:
trivy --db-repository ghcr.io/aquasecurity/trivy-db:2 image alpine:latestWorking with the server
When something is wrong in client/server mode:
- Run the server with
--debugand--listen :8080. - Run the client with
--debug --server http://localhost:8080. - Compare the request/response logs. The Twirp protocol is HTTP+JSON by default, so
tcpdumpor a logging proxy works.
The RPC plumbing is in pkg/rpc/client/ and pkg/rpc/server/; the wire conversions are in pkg/rpc/convert.go.
Profiling
The CLI does not expose pprof directly, but you can wire it up locally:
import _ "net/http/pprof"
go func() { _ = http.ListenAndServe("localhost:6060", nil) }()Add this to cmd/trivy/main.go for a one-off profile. The hot paths are typically in the walker (file IO) and in vulnerability detection (DB lookups).
Common errors
failed to download vulnerability DB— network or registry access; try--db-repository ghcr.io/aquasecurity/trivy-db:2or setTRIVY_INSECURE=truefor self-signed registries.unknown OS— the analyzer registry could not detect the distribution. Add--debugand inspect the analyzer log lines.policy initialization error— the Trivy Checks bundle could not be downloaded; pass--skip-policy-updateor--config-policy <path>for an offline alternative.no such directory: /trivy/cache— your--cache-dirdoes not exist; create it first.
See also
- Patterns and conventions — error handling and
xerrorswrapping. - Tooling — Mage tasks, lint config.
- Cache system — how cache keys and blobs work.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.