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¶
Setting TRIVY_ENABLED=false (also accepts 0, no, off) fully disarms
Trivy:
supervisordnever starts thetrivy-serverprocess.- The vulnerability database updater is skipped.
- Every scan endpoint (
GET /api/trivy/scan,/api/trivy/db, …) returns503 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).