name: "Trivy scan (image)" description: "Run trivy image in a locked-down Docker container; report is always SARIF" author: "Timo Behrendt " branding: icon: "package" color: "blue" inputs: image: description: "Container image reference to scan (pulled by Trivy inside the container; requires network)" required: true cache-dir: description: "Host path to the Trivy cache directory (mounted read-only at /cache; use the same path as setup-db)" required: false default: "${{ runner.temp }}/trivy" output-dir: description: "Host directory where the report file is written (mounted read-write at /out)" required: true output-file: description: "SARIF report file name only (no slashes); written under output-dir" required: true trivy-version: description: "Trivy Docker image reference (digest pin recommended)" required: false default: "ghcr.io/aquasecurity/trivy:0.69.3@sha256:bcc376de8d77cfe086a917230e818dc9f8528e3c852f7b1aff648949b6258d1c" outputs: output-path: description: "Host path to the generated report file" value: ${{ steps.scan.outputs.output-path }} runs: using: "composite" steps: - id: scan shell: bash env: IMAGE_REF: ${{ inputs.image }} CACHE_DIR_IN: ${{ inputs.cache-dir }} OUTPUT_DIR_IN: ${{ inputs.output-dir }} OUTPUT_FILE: ${{ inputs.output-file }} TRIVY_IMAGE: ${{ inputs.trivy-version }} run: | set -euo pipefail case "$OUTPUT_FILE" in */*|".."*) echo "FAIL: output-file must be a single file name (no path separators)"; exit 1 ;; esac cache_dir=$(realpath "$CACHE_DIR_IN") mkdir -p "$OUTPUT_DIR_IN" output_dir=$(realpath "$OUTPUT_DIR_IN") test -d "$cache_dir" || { echo "FAIL: cache-dir is not a directory: $cache_dir"; exit 1; } docker run --rm \ --name trivy-scan-image \ --user "$(id -u):$(id -g)" \ --read-only \ --env-file /dev/null \ --cap-drop ALL \ --pids-limit 64 \ --memory=512m \ --memory-swap=512m \ --cpus=1 \ --ipc private \ --cgroupns private \ --security-opt no-new-privileges \ --security-opt apparmor=docker-default \ --tmpfs /tmp:rw,noexec,nosuid,nodev,size=1g \ --mount type=bind,src="$cache_dir",dst=/cache,ro \ --mount type=bind,src="$output_dir",dst=/out \ "$TRIVY_IMAGE" \ image "$IMAGE_REF" \ --cache-dir /cache \ --skip-db-update \ --offline-scan \ --format sarif \ --exit-code 0 \ -o "/out/$OUTPUT_FILE" echo "output-path=$output_dir/$OUTPUT_FILE" >> "$GITHUB_OUTPUT"