From a0790501083b8981986978d13f936d15cf8f3bfa Mon Sep 17 00:00:00 2001 From: librelad Date: Thu, 16 Jul 2026 16:59:59 +0100 Subject: [PATCH] fix(trivy): scan local images via the mounted socket, not a registry pull MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The client scan resolved images by pulling from Docker Hub, which fails on an offline/privacy box ("index.docker.io ... network is unreachable") — yet every installed app's image is already present locally. Point Trivy at the docker socket that's already bind-mounted into the container (--image-src docker, plus DOCKER_HOST=unix:///run/user//docker.sock for rootless, derived from the install user — rooted's default path is found automatically). Scans local images with zero network. Verified: aquasec/trivy:latest -> 28 CVEs. Co-Authored-By: Claude Opus 4.8 (1M context) --- containers/trivy/scripts/trivy_scan.sh | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/containers/trivy/scripts/trivy_scan.sh b/containers/trivy/scripts/trivy_scan.sh index c1ab637..ad1a205 100644 --- a/containers/trivy/scripts/trivy_scan.sh +++ b/containers/trivy/scripts/trivy_scan.sh @@ -54,13 +54,23 @@ trivyScanImageCves() { [ -n "$image" ] || { echo '[]'; return; } command -v jq >/dev/null 2>&1 || { echo '[]'; return; } - # Scan in CLIENT mode against the running server (--server localhost:4954, - # the container's fixed --listen port). Standalone `trivy image` would try to - # open the vuln-DB cache the server already holds and fail with a cache-lock - # timeout; client mode leaves the DB to the server. --quiet keeps the - # progress spinner out of stdout; we only want CRITICAL..LOW findings. + # Scan the app's LOCAL image via the docker socket mounted into the + # container (--image-src docker) so nothing is pulled from a registry — the + # image is already present, and a privacy box may have no outbound at all. + # Client mode (--server localhost:4954, the container's fixed --listen port) + # leaves the vuln DB to the running server; a standalone scan would deadlock + # on the server's cache lock. For rootless the daemon socket lives under + # /run/user/ (not trivy's default path), so point DOCKER_HOST at it; + # rooted's /var/run/docker.sock is found by default. + local envs="" + if [ "${CFG_DOCKER_INSTALL_TYPE:-}" = "rootless" ] && [ -n "${docker_install_user:-}" ]; then + local uid; uid="$(id -u "$docker_install_user" 2>/dev/null)" + [ -n "$uid" ] && envs="-e DOCKER_HOST=unix:///run/user/$uid/docker.sock" + fi + + # --quiet keeps the progress spinner out of stdout; we only want CRITICAL..LOW. local raw - raw="$(dockerCommandRun "docker exec trivy-service trivy image --server http://localhost:4954 --quiet --scanners vuln --format json --severity CRITICAL,HIGH,MEDIUM,LOW '$image'" 2>/dev/null)" + raw="$(dockerCommandRun "docker exec $envs trivy-service trivy image --server http://localhost:4954 --image-src docker --quiet --scanners vuln --format json --severity CRITICAL,HIGH,MEDIUM,LOW '$image'" 2>/dev/null)" [ -n "$raw" ] || { echo '[]'; return; } printf '%s' "$raw" | jq -c '