From bd926049124049659ac11a0708e8870ed1d579c2 Mon Sep 17 00:00:00 2001 From: dresber Date: Thu, 13 Aug 2026 14:45:44 +0200 Subject: [PATCH] fix trivy vulnerability DB update outage --- .gitea/workflows/docker-publish.yml | 24 ++++++++++++++++++++++ .gitea/workflows/image-security-checks.yml | 24 ++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/.gitea/workflows/docker-publish.yml b/.gitea/workflows/docker-publish.yml index 8bc6eef..1ac9a06 100644 --- a/.gitea/workflows/docker-publish.yml +++ b/.gitea/workflows/docker-publish.yml @@ -180,11 +180,35 @@ jobs: fi trivy --version + # Trivy's default vulnerability-DB source (mirror.gcr.io/aquasec/trivy-db) is a + # Google-hosted cache of the upstream GHCR image, used to dodge GHCR's unauthenticated + # rate limits. That cache occasionally 404s on a specific layer digest (a known, + # recurring upstream issue: aquasecurity/trivy). Point at the canonical GHCR source + # instead, and retry the DB download alone a few times — trivy exits 1 both for "DB + # download failed" and for "vulnerabilities found", so the download is a separate step + # from the scan to keep those two outcomes distinguishable. + export TRIVY_DB_REPOSITORY="ghcr.io/aquasecurity/trivy-db:2" + export TRIVY_JAVA_DB_REPOSITORY="ghcr.io/aquasecurity/trivy-java-db:1" + + echo "=== Ensuring vulnerability DB is up to date ===" + db_attempt=1 + db_max_attempts=3 + until trivy image --download-db-only; do + if [ "$db_attempt" -ge "$db_max_attempts" ]; then + echo "=== Failed to download the Trivy vulnerability DB after ${db_max_attempts} attempts ===" + exit 1 + fi + echo "=== DB download failed, retrying (${db_attempt}/${db_max_attempts})... ===" + db_attempt=$((db_attempt + 1)) + sleep $((db_attempt * 5)) + done + echo "=== Scanning ${{ steps.vars.outputs.scan_ref }} (fail on fixable ${{ inputs.scan_severity }}) ===" trivy image \ --exit-code 1 \ --severity "${{ inputs.scan_severity }}" \ --ignore-unfixed \ + --skip-db-update \ --scanners vuln,secret \ "${{ steps.vars.outputs.scan_ref }}" diff --git a/.gitea/workflows/image-security-checks.yml b/.gitea/workflows/image-security-checks.yml index 8fe9cc5..c1c6501 100644 --- a/.gitea/workflows/image-security-checks.yml +++ b/.gitea/workflows/image-security-checks.yml @@ -61,10 +61,34 @@ jobs: FULL_IMAGE="${{ secrets.DOCKER_REGISTRY }}/${{ inputs.image_name }}:${{ inputs.image_tag }}" + # Trivy's default vulnerability-DB source (mirror.gcr.io/aquasec/trivy-db) is a + # Google-hosted cache of the upstream GHCR image, used to dodge GHCR's unauthenticated + # rate limits. That cache occasionally 404s on a specific layer digest (a known, + # recurring upstream issue: aquasecurity/trivy). Point at the canonical GHCR source + # instead, and retry the DB download alone a few times — trivy exits 1 both for "DB + # download failed" and for "vulnerabilities found", so the download is a separate step + # from the scan to keep those two outcomes distinguishable. + export TRIVY_DB_REPOSITORY="ghcr.io/aquasecurity/trivy-db:2" + export TRIVY_JAVA_DB_REPOSITORY="ghcr.io/aquasecurity/trivy-java-db:1" + + echo "=== Ensuring vulnerability DB is up to date ===" + db_attempt=1 + db_max_attempts=3 + until trivy image --download-db-only; do + if [ "$db_attempt" -ge "$db_max_attempts" ]; then + echo "=== Failed to download the Trivy vulnerability DB after ${db_max_attempts} attempts ===" + exit 1 + fi + echo "=== DB download failed, retrying (${db_attempt}/${db_max_attempts})... ===" + db_attempt=$((db_attempt + 1)) + sleep $((db_attempt * 5)) + done + echo "=== Scanning ${FULL_IMAGE} (fail on fixable ${{ inputs.scan_severity }}) ===" trivy image \ --exit-code 1 \ --severity "${{ inputs.scan_severity }}" \ --ignore-unfixed \ + --skip-db-update \ --scanners vuln,secret \ "${FULL_IMAGE}"