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, whether running locally or remotely:
supervisordnever starts the embeddedtrivy-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.
Local vs. remote Trivy server¶
Portalcrane always talks to Trivy in client/server mode
(trivy image --server <url>). By default TRIVY_SERVER_URL points at the
trivy-server process embedded in the same container. Pointing it at a
different host instead runs the scan against a Trivy server running in
another container — useful to share one Trivy instance (and its CVE
database) across several Portalcrane deployments, or to keep the vulnerability
DB off the main container entirely:
# docker-compose.yml sketch
services:
trivy:
image: aquasec/trivy
command: server --listen 0.0.0.0:4954
volumes:
- trivy-cache:/root/.cache/trivy
portalcrane:
image: ghcr.io/cyr-ius/portalcrane
environment:
TRIVY_ENABLED: "true"
TRIVY_SERVER_URL: "http://trivy:4954"
When TRIVY_SERVER_URL no longer targets localhost/127.0.0.1:
- The embedded
trivy-serveris not autostarted bysupervisord— no point running a local server nobody talks to. - The local vulnerability database updater is skipped too; the remote server manages its own DB.
GET /api/trivy/dbandPOST /api/trivy/db/updatereport the DB as managed remotely instead of reading the (now-empty) local cache — check the remote server's own status for its DB freshness.- Actual scanning (
GET /api/trivy/scan, the staging pipeline, transfers) is unaffected — it just talks to the remote server instead of the local one.
TRIVY_ENABLED stays the single switch for turning scanning on or off in
either mode; TRIVY_SERVER_URL only decides where Trivy runs.
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
or transfer job whose scan surfaces a blocking severity is flagged in the
job's vuln_result and the push is refused server-side (403 on
POST /api/staging/push; the transfer stops at scan_vulnerable without
pushing) — retag away the offending layer, choose a patched base image, or
abandon the job.
An admin can grant specific accounts a standing exception to this block — see Vulnerability-block bypass in the users & permissions guide.