Enabling and Using Trivy Vulnerability Scanning in Harbor
Enable Harbor's built-in Trivy scanner by editing harbor.yml, restart services, push a test image, and verify vulnerability reports in the UI or via API. Covers offline DB updates, concurrency limits, and common misconfigurations.
02 Aug 2025, 01:04 UTC

The Problem: Harbor Needs a Vulnerability Scanner
Harbor does not scan container images for vulnerabilities out of the box. You must enable and configure a scanner. The built‑in Trivy integration is the most common choice because it requires no external service and updates its vulnerability database automatically.
Enable Trivy in harbor.yml
Edit the Harbor configuration file (usually /etc/harbor/harbor.yml or harbor.yml in your deployment directory) and add a scanner section under the top‑level keys:
scanner:
trivy:
updateInterval: 24h # how often to refresh the Trivy DB
# proxy: http://proxy.example.com:3128 # uncomment if outbound traffic requires a proxy
# skipUpdate: false # set true only for fully offline environments
After saving, reconfigure and restart Harbor:
# Run from the Harbor installer directory
./prepare
./install.sh
This restarts the scanner-trivy container and the core services. The scanner will download the latest Trivy vulnerability database on startup and then every updateInterval.
Verify the Scanner Is Running
Check the scanner logs for a successful startup and DB update:
docker logs scanner-trivy 2>&1 | grep -E 'Trivy scanner started|DB updated successfully'
You should see lines indicating the scanner started and the database was updated. If the DB update fails, the host likely lacks outbound HTTPS (port 443) access to ghcr.io and github.com where Trivy fetches its database.
Trigger a Scan: Push an Image
Harbor scans images automatically on push. Use a test image to confirm the pipeline works:
docker pull alpine:latest
docker tag alpine:latest harbor.example.com/library/alpine:test
docker push harbor.example.com/library/alpine:test
Replace harbor.example.com with your Harbor hostname. After the push completes, wait a minute or two for the scan to finish.
View Results in the UI and via API
In the Harbor web UI, navigate to the project → repository → Artifacts tab, click the artifact digest, then open the Vulnerabilities tab. You will see a severity breakdown (Critical, High, Medium, Low) and a list of CVEs.
To retrieve the same data programmatically, use the scanner report endpoint:
curl -u admin:Harbor12345 \
"https://harbor.example.com/api/v2.0/scanner/reports?artifact=sha256:<digest>"
The response contains a summary object with counts per severity, confirming the scanner processed the image.
Limitations You Should Know
- OCI/Docker images only. Helm charts, OCI artifacts, and other content types are not scanned unless they are packaged as container images.
- Database freshness depends on outbound internet. Without access to the Trivy DB endpoints, the scanner falls back to a stale database and will miss newly published CVEs.
- No runtime or configuration scanning. Trivy in Harbor only analyzes the image layers; it does not evaluate Kubernetes manifests, IaC files, or running containers.
- Scan concurrency can overload the database. Setting a high
scanAllPolicyconcurrency or pushing many large images simultaneously may cause Harbor's PostgreSQL to time out.
Common Mistakes and How to Avoid Them
1. Forgetting Outbound Network Access
If the Harbor host sits in a restricted network, the Trivy DB update will fail silently. The scanner logs will show failed to download DB errors. Fix by allowing HTTPS egress to ghcr.io and github.com, or by configuring a proxy in the scanner.trivy.proxy field.
2. Misaligned Update Schedule and Garbage Collection
Harbor's garbage collection (GC) removes unreferenced blobs. If GC runs immediately after a DB update but before the next scan, the new vulnerability definitions may not be applied to existing artifacts until they are re‑scanned. Schedule GC to run after the DB update window, or trigger a manual re‑scan of critical images after each DB refresh.
3. Excessive Scan Concurrency
The scanAllPolicy parameter (set via the API or UI) controls how many concurrent scans run. A value higher than 5 on a modest Harbor instance often leads to database connection exhaustion. Start with the default (usually 3) and increase only after monitoring PostgreSQL connection usage.
Practical Verification Checklist
- After restarting Harbor, confirm
Trivy scanner startedandDB updated successfullyappear indocker logs scanner-trivy. - Push a test image (e.g.,
alpine:latest) to a Harbor project. - Within a few minutes, open the artifact's Vulnerabilities tab in the UI and verify a severity summary appears.
- Run the API call
GET /api/v2.0/scanner/reports?artifact=<digest>and confirm the JSON contains asummaryfield with non‑zero counts.
Offline Environments
If your Harbor cluster has no internet access, you must mirror the Trivy database. The typical workflow:
- On a machine with internet, run
trivy image --download-db-onlyto fetch the DB. - Copy the resulting
trivy.dbfile to the Harbor scanner container's/root/.cache/trivy/db/directory. - Set
skipUpdate: trueinharbor.ymlso the scanner does not attempt outbound connections. - Repeat the manual DB copy on your desired schedule (e.g., daily via a cron job).
Note: This process is not officially automated by Harbor; you must maintain the copy mechanism yourself.
Version Assumptions
This guide applies to Harbor v2.8+ with the bundled Trivy scanner (Trivy v0.48+). Earlier versions used the Clair scanner by default and require different configuration keys.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.