Skip to content

Vulnerability Scanning (Trivy)

Portalcrane embeds Trivy as a persistent server process (trivy-server, listening on 127.0.0.1:4954), so scans don't pay a cold-start cost. It's used in two places: the Staging Pipeline, where it gates a push based on severity, and on-demand scans triggered from the image browser.

Master switch

TRIVY_ENABLED=true   # default

Setting TRIVY_ENABLED=false (also accepts 0, no, off) fully disarms Trivy:

  • supervisord never starts the trivy-server process.
  • The vulnerability database updater is skipped.
  • Every scan endpoint (GET /api/trivy/scan, /api/trivy/db, …) returns 503 Service Unavailable.
  • The staging pipeline silently skips the scan step regardless of VULN_SCAN_ENABLED.

Use this on resource-constrained hosts (e.g. a Raspberry Pi) where you'd rather trade vulnerability scanning for a smaller memory footprint.

Scan policy

Variable Description Default
VULN_SCAN_ENABLED Enable the CVE scan step in the staging pipeline true
VULN_SCAN_SEVERITIES Comma-separated severities that block a staging push CRITICAL,HIGH
VULN_IGNORE_UNFIXED Ignore CVEs that have no available fix yet false
VULN_SCAN_TIMEOUT Timeout for a single Trivy scan 5m

These four values can be overridden globally, for all users, from Settings → Vulnerability Scanning — the override is persisted to DATA_DIR/vuln_override.json and takes precedence over the environment variables on the next request, no restart needed.

curl -X PUT http://<host>:8000/api/trivy/override \
  -H "Authorization: Bearer <admin-token>" \
  -H "Content-Type: application/json" \
  -d '{
        "vuln_scan_enabled": true,
        "vuln_scan_severities": "CRITICAL,HIGH,MEDIUM",
        "vuln_ignore_unfixed": true,
        "vuln_scan_timeout": "10m"
      }'

Remove the override with DELETE /api/trivy/override to fall back to the environment-variable defaults.

Per-job overrides

The Staging Pipeline's pull request (POST /api/staging/pull) also accepts vuln_scan_enabled_override and vuln_severities_override fields, letting a user relax or tighten the policy for a single pull without touching the global setting.

On-demand scanning

Any authenticated user can scan an already-pushed image directly:

curl -G http://<host>:8000/api/trivy/scan \
  -H "Authorization: Bearer <token>" \
  --data-urlencode "image=production/redis:7.2" \
  --data-urlencode "severity=HIGH" \
  --data-urlencode "severity=CRITICAL" \
  --data-urlencode "ignore_unfixed=false"

The image reference must include an explicit tag or digest (e.g. production/redis:7.2 or production/redis@sha256:…) — a bare repository name is rejected with 400.

Database maintenance (admin)

The Trivy vulnerability database is cached under DATA_DIR/cache/trivy/ and updates automatically in the background. Admins can check its freshness and force a refresh from Settings → System:

# Freshness / metadata
curl http://<host>:8000/api/trivy/db -H "Authorization: Bearer <admin-token>"

# Force an immediate update
curl -X POST http://<host>:8000/api/trivy/db/update -H "Authorization: Bearer <admin-token>"

Reading a scan result

Scan results are grouped and include CVSS scores, so the UI can sort by severity and show a fix-available indicator per vulnerability. A staging job whose scan surfaces a blocking severity is flagged in the job's vuln_result; the push step is left to the operator's judgment — Portalcrane surfaces the risk, it does not silently refuse to push a flagged image (you decide whether to proceed, retag away the offending layer, or abandon the job).