From 368e1be8dd016a8443bfeeba6e87774837a625a5 Mon Sep 17 00:00:00 2001 From: Timo Behrendt Date: Sat, 18 Jul 2026 10:24:01 +0200 Subject: [PATCH] refactor!: to osv-scanner (#51) Reviewed-on: https://gitea.t000-n.de/t.behrendt/sec-actions/pulls/51 Co-authored-by: Timo Behrendt Co-committed-by: Timo Behrendt --- .gitea/workflows/ci.yaml | 35 +++++++++---- README.md | 4 +- setup-db/README.md | 32 ++++++++---- setup-db/action.yaml | 79 +++++++++++++++++++++++++---- setup-osv/README.md | 51 +++++++++++++++++++ setup-osv/action.yaml | 104 +++++++++++++++++++++++++++++++++++++++ setup-trivy/README.md | 39 --------------- setup-trivy/action.yaml | 68 ------------------------- 8 files changed, 274 insertions(+), 138 deletions(-) create mode 100644 setup-osv/README.md create mode 100644 setup-osv/action.yaml delete mode 100644 setup-trivy/README.md delete mode 100644 setup-trivy/action.yaml diff --git a/.gitea/workflows/ci.yaml b/.gitea/workflows/ci.yaml index 76900e9..9f57abb 100644 --- a/.gitea/workflows/ci.yaml +++ b/.gitea/workflows/ci.yaml @@ -4,20 +4,24 @@ on: pull_request: jobs: - test-setup-trivy: + test-setup-osv: strategy: matrix: arch: [amd64, arm64] - name: Test Setup Trivy ${{ matrix.arch }} + name: Test Setup OSV Scanner ${{ matrix.arch }} runs-on: - ubuntu-latest - linux_${{ matrix.arch }} steps: - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - - name: Setup Trivy - uses: ./setup-trivy - - name: Run Trivy - run: trivy --version + - name: Setup OSV Scanner + uses: ./setup-osv + with: + version: v2.4.0 + amd64-digest: 15314940c10d26af9c6649f150b8a47c1262e8fc7e17b1d1029b0e479e8ed8a0 + arm64-digest: 44e580752910f0ff36ec99aff59af20f65df1e859aa31e5605a8f0d055b496e9 + - name: Run osv-scanner + run: osv-scanner --version test-setup-db: name: Test Setup DB @@ -25,12 +29,25 @@ jobs: - ubuntu-latest steps: - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - - uses: ./setup-trivy + - uses: ./setup-osv + with: + version: v2.4.0 + amd64-digest: 15314940c10d26af9c6649f150b8a47c1262e8fc7e17b1d1029b0e479e8ed8a0 + arm64-digest: 44e580752910f0ff36ec99aff59af20f65df1e859aa31e5605a8f0d055b496e9 - name: Setup DB id: setup-db uses: ./setup-db - - name: Run Trivy - run: trivy fs --skip-db-update --cache-dir ${{ steps.setup-db.outputs.cache-dir }} . + with: + # Keep CI fast; full ecosystem download is covered by the action default. + ecosystems: Go,npm,PyPI + - name: Run osv-scanner offline + run: | + test -n "${OSV_SCANNER_LOCAL_DB_CACHE_DIRECTORY}" + test "${OSV_SCANNER_LOCAL_DB_CACHE_DIRECTORY}" = "${{ steps.setup-db.outputs.cache-dir }}" + test -f "${OSV_SCANNER_LOCAL_DB_CACHE_DIRECTORY}/osv-scanner/Go/all.zip" + test -f "${OSV_SCANNER_LOCAL_DB_CACHE_DIRECTORY}/osv-scanner/npm/all.zip" + test -f "${OSV_SCANNER_LOCAL_DB_CACHE_DIRECTORY}/osv-scanner/PyPI/all.zip" + osv-scanner scan source --offline-vulnerabilities --allow-no-lockfiles . test-get-images-from-files: name: Test Get Images From Files diff --git a/README.md b/README.md index ae0b575..351456e 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,3 @@ -# Trivy Actions +# OSV Scanner Actions -Gitea compatible actions related to Trivy or the Trivy ecosystem. +Gitea compatible actions related to osv-scanner or the OSV ecosystem. diff --git a/setup-db/README.md b/setup-db/README.md index 4f59fa2..45fbf65 100644 --- a/setup-db/README.md +++ b/setup-db/README.md @@ -1,8 +1,8 @@ # Setup DB Action -A reusable Gitea Action that sets up the Trivy vulnerability database, restoring from cache if available. +A reusable Gitea Action that sets up the osv-scanner offline vulnerability database, restoring from cache if available. -**Note:** This action only sets up the database. Trivy itself must be installed separately (e.g., using the `setup-trivy` action). +**Note:** This action only sets up the database. osv-scanner itself must be installed separately (e.g., using the `setup-osv` action). Subsequent steps receive `OSV_SCANNER_LOCAL_DB_CACHE_DIRECTORY` via the environment. ## Usage @@ -10,7 +10,7 @@ A reusable Gitea Action that sets up the Trivy vulnerability database, restoring ```yaml - name: Setup DB - uses: https://gitea.t000-n.de/t.behrendt/trivy-actions/setup-db@0.0.1 + uses: https://gitea.t000-n.de/t.behrendt/osv-scanner-actions/setup-db@0.0.1 ``` ### Complete Example @@ -26,16 +26,28 @@ jobs: - linux_amd64 steps: - uses: actions/checkout@v4 - - name: Setup Trivy - uses: https://gitea.t000-n.de/t.behrendt/trivy-actions/setup-trivy@0.0.1 + - name: Setup OSV Scanner + uses: https://gitea.t000-n.de/t.behrendt/osv-scanner-actions/setup-osv@0.0.1 + with: + version: "v2.4.0" + amd64-digest: "15314940c10d26af9c6649f150b8a47c1262e8fc7e17b1d1029b0e479e8ed8a0" + arm64-digest: "44e580752910f0ff36ec99aff59af20f65df1e859aa31e5605a8f0d055b496e9" - name: Setup DB - uses: https://gitea.t000-n.de/t.behrendt/trivy-actions/setup-db@0.0.1 + id: setup-db + uses: https://gitea.t000-n.de/t.behrendt/osv-scanner-actions/setup-db@0.0.1 - name: Scan for vulnerabilities - run: trivy fs . + run: osv-scanner scan source --offline-vulnerabilities -r . ``` ## Inputs -| Input | Description | Required | Default | -| ----------- | --------------------------------- | -------- | ---------------- | -| `cache-dir` | Path to the Trivy cache directory | No | `~/.cache/trivy` | +| Input | Description | Required | Default | +| ------------- | --------------------------------------------------------------------------- | -------- | -------------------------------- | +| `cache-dir` | Path used as `OSV_SCANNER_LOCAL_DB_CACHE_DIRECTORY` | No | `${{ runner.temp }}/osv-scanner` | +| `ecosystems` | Comma-separated OSV ecosystems to download; empty downloads all ecosystems | No | _(all)_ | + +## Outputs + +| Output | Description | +| ----------- | ------------------------------------------------ | +| `cache-dir` | Path to the osv-scanner local DB cache directory | diff --git a/setup-db/action.yaml b/setup-db/action.yaml index f41a89b..db1d631 100644 --- a/setup-db/action.yaml +++ b/setup-db/action.yaml @@ -1,19 +1,23 @@ -name: "Setup Trivy DB" -description: "Setup the trivy database, restoring from cache if available" -author: "Timo Behrendt " branding: icon: "database" color: "blue" inputs: cache-dir: - description: "Path to the Trivy cache directory (default: ${{runner.temp}}/trivy)" + description: "Path used as OSV_SCANNER_LOCAL_DB_CACHE_DIRECTORY (default: ${{runner.temp}}/osv-scanner)" required: false - default: "${{ runner.temp }}/trivy" + default: "${{ runner.temp }}/osv-scanner" + ecosystems: + description: "Comma-separated list of OSV ecosystems to download. Empty downloads all ecosystems." + required: false + default: "" outputs: cache-dir: - description: "Path to the Trivy cache directory" + description: "Path to the osv-scanner local DB cache directory" value: ${{ inputs.cache-dir }} runs: @@ -27,9 +31,64 @@ runs: uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: ${{ inputs.cache-dir }} - key: trivy-db-${{ steps.current-date.outputs.current-date }} + key: osv-scanner-db-${{ steps.current-date.outputs.current-date }} restore-keys: | - trivy-db-${{ steps.current-date.outputs.current-date }} - - if: steps.restore-db.outputs.cache-hit != 'true' + osv-scanner-db-${{ steps.current-date.outputs.current-date }} + - name: Download offline databases + if: steps.restore-db.outputs.cache-hit != 'true' shell: bash - run: trivy fs --download-db-only --cache-dir "${{ inputs.cache-dir }}" + run: | + set -euo pipefail + + CACHE_DIR="${{ inputs.cache-dir }}" + DB_DIR="${CACHE_DIR}/osv-scanner" + mkdir -p "${DB_DIR}" + + ECOSYSTEMS_INPUT="${{ inputs.ecosystems }}" + if [ -n "${ECOSYSTEMS_INPUT}" ]; then + # shellcheck disable=SC2001 + ECOSYSTEMS=$(echo "${ECOSYSTEMS_INPUT}" | tr ',' '\n' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | grep -v '^$' || true) + else + ECOSYSTEMS=$(curl -fsSL https://osv-vulnerabilities.storage.googleapis.com/ecosystems.txt | grep -v '^$' | grep -v '^\[EMPTY\]$' || true) + fi + + if [ -z "${ECOSYSTEMS}" ]; then + echo "No ecosystems to download" >&2 + exit 1 + fi + + download_one() { + local ecosystem="$1" + local encoded + encoded=$(printf '%s' "${ecosystem}" | jq -sRr @uri) + local dest="${DB_DIR}/${ecosystem}" + mkdir -p "${dest}" + echo "Downloading ${ecosystem}..." + curl -fsSL "https://osv-vulnerabilities.storage.googleapis.com/${encoded}/all.zip" -o "${dest}/all.zip" + } + + max_jobs=8 + pids=() + while IFS= read -r ecosystem; do + [ -z "${ecosystem}" ] && continue + while [ "$(jobs -rp | wc -l)" -ge "${max_jobs}" ]; do + sleep 0.2 + done + download_one "${ecosystem}" & + pids+=("$!") + done <<< "${ECOSYSTEMS}" + + fail=0 + for pid in "${pids[@]}"; do + wait "${pid}" || fail=1 + done + if [ "${fail}" -ne 0 ]; then + echo "One or more ecosystem database downloads failed" >&2 + exit 1 + fi + + echo "Downloaded $(find "${DB_DIR}" -name all.zip | wc -l) ecosystem database(s) to ${DB_DIR}" + - name: Export DB cache directory + shell: bash + run: | + echo "OSV_SCANNER_LOCAL_DB_CACHE_DIRECTORY=${{ inputs.cache-dir }}" >> "$GITHUB_ENV" diff --git a/setup-osv/README.md b/setup-osv/README.md new file mode 100644 index 0000000..ed0115d --- /dev/null +++ b/setup-osv/README.md @@ -0,0 +1,51 @@ +# Setup OSV Scanner Action + +A reusable Gitea Action that downloads and sets up the osv-scanner binary for vulnerability scanning. + +The downloaded binary is verified against a pinned SHA-256 digest for the runner architecture. + +## Usage + +### Basic Usage + +```yaml +- name: Setup OSV Scanner + uses: your-username/osv-scanner-actions@main/setup-osv + with: + version: "v2.4.0" + amd64-digest: "15314940c10d26af9c6649f150b8a47c1262e8fc7e17b1d1029b0e479e8ed8a0" + arm64-digest: "44e580752910f0ff36ec99aff59af20f65df1e859aa31e5605a8f0d055b496e9" +``` + +Digests are published in each release's `osv-scanner_SHA256SUMS` file (e.g. for `osv-scanner_linux_amd64` / `osv-scanner_linux_arm64`). You may pass either bare hex or `sha256:`. + +### Complete Example + +```yaml +name: Security Scan +on: [push, pull_request] + +jobs: + security: + runs-on: + - ubuntu-latest + - linux_amd64 + steps: + - uses: actions/checkout@v4 + - name: Setup OSV Scanner + uses: your-username/osv-scanner-actions@main/setup-osv + with: + version: "v2.4.0" + amd64-digest: "15314940c10d26af9c6649f150b8a47c1262e8fc7e17b1d1029b0e479e8ed8a0" + arm64-digest: "44e580752910f0ff36ec99aff59af20f65df1e859aa31e5605a8f0d055b496e9" + - name: Scan for vulnerabilities + run: osv-scanner scan source -r . +``` + +## Inputs + +| Input | Description | Required | Default | +| -------------- | -------------------------------------------------------------------- | -------- | ------- | +| `version` | Explicit osv-scanner release tag (e.g. `v2.4.0`). `latest` is rejected | Yes | — | +| `amd64-digest` | SHA-256 of `osv-scanner_linux_amd64` (hex or `sha256:`) | Yes | — | +| `arm64-digest` | SHA-256 of `osv-scanner_linux_arm64` (hex or `sha256:`) | Yes | — | diff --git a/setup-osv/action.yaml b/setup-osv/action.yaml new file mode 100644 index 0000000..1d52d4b --- /dev/null +++ b/setup-osv/action.yaml @@ -0,0 +1,104 @@ +name: "Setup OSV Scanner" +description: "Download and setup osv-scanner binary for vulnerability scanning" +author: "Gitea Actions" +branding: + icon: "shield" + color: "blue" + +inputs: + version: + description: "osv-scanner version to download (e.g., v2.4.0). Must be an explicit release tag; 'latest' is not allowed." + required: true + amd64-digest: + description: "SHA-256 digest of the linux amd64 binary (hex or sha256:)" + required: true + arm64-digest: + description: "SHA-256 digest of the linux arm64 binary (hex or sha256:)" + required: true + +runs: + using: "composite" + steps: + - name: Resolve architecture and digest + shell: bash + id: arch + run: | + set -euo pipefail + + VERSION="${{ inputs.version }}" + if [ -z "${VERSION}" ] || [ "${VERSION}" = "latest" ]; then + echo "version must be an explicit release tag (e.g. v2.4.0); 'latest' is not allowed" >&2 + exit 1 + fi + + case "$(uname -m)" in + x86_64) + ARCH="amd64" + DIGEST="${{ inputs.amd64-digest }}" + ;; + aarch64) + ARCH="arm64" + DIGEST="${{ inputs.arm64-digest }}" + ;; + *) + echo "Unsupported architecture: $(uname -m)" >&2 + exit 1 + ;; + esac + + if [ -z "${DIGEST}" ]; then + echo "Missing digest for architecture ${ARCH}" >&2 + exit 1 + fi + + # Normalize sha256: / SHA256: to bare hex + DIGEST="${DIGEST#sha256:}" + DIGEST="${DIGEST#SHA256:}" + + if ! [[ "${DIGEST}" =~ ^[a-fA-F0-9]{64}$ ]]; then + echo "Invalid ${ARCH} digest (expected 64-char hex or sha256:): ${DIGEST}" >&2 + exit 1 + fi + + echo "ARCH=${ARCH}" >> "$GITHUB_OUTPUT" + echo "DIGEST=${DIGEST}" >> "$GITHUB_OUTPUT" + echo "VERSION=${VERSION}" >> "$GITHUB_OUTPUT" + - name: Cache osv-scanner binary + id: cache-osv + uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + path: /usr/local/bin/osv-scanner + key: osv-scanner-${{ steps.arch.outputs.version }}-${{ steps.arch.outputs.arch }}-${{ steps.arch.outputs.digest }} + restore-keys: | + osv-scanner-${{ steps.arch.outputs.version }}-${{ steps.arch.outputs.arch }}-${{ steps.arch.outputs.digest }} + - name: Download and install osv-scanner + if: steps.cache-osv.outputs.cache-hit != 'true' + shell: bash + run: | + set -euo pipefail + + VERSION="${{ steps.arch.outputs.version }}" + ARCH="${{ steps.arch.outputs.arch }}" + EXPECTED_DIGEST="${{ steps.arch.outputs.digest }}" + DEST="/usr/local/bin/osv-scanner" + + mkdir -p /usr/local/bin + + curl -fsSL "https://github.com/google/osv-scanner/releases/download/${VERSION}/osv-scanner_linux_${ARCH}" -o "${DEST}" + + ACTUAL_DIGEST=$(sha256sum "${DEST}" | awk '{print $1}') + if [ "${ACTUAL_DIGEST}" != "${EXPECTED_DIGEST}" ]; then + echo "Digest mismatch for osv-scanner ${VERSION} (linux_${ARCH})" >&2 + echo " expected: ${EXPECTED_DIGEST}" >&2 + echo " actual: ${ACTUAL_DIGEST}" >&2 + rm -f "${DEST}" + exit 1 + fi + + chmod +x "${DEST}" + echo "Verified osv-scanner ${VERSION} (linux_${ARCH}) digest ${ACTUAL_DIGEST}" + + - name: Add osv-scanner to PATH + shell: bash + run: | + echo "/usr/local/bin" >> "$GITHUB_PATH" diff --git a/setup-trivy/README.md b/setup-trivy/README.md deleted file mode 100644 index 78e877f..0000000 --- a/setup-trivy/README.md +++ /dev/null @@ -1,39 +0,0 @@ -# Setup Trivy Action - -A reusable Gitea Action that downloads and sets up the Trivy binary for vulnerability scanning. - -## Usage - -### Basic Usage - -```yaml -- name: Setup Trivy - uses: your-username/trivy-actions@main/setup-trivy - with: - version: "v0.66.0" # Optional: Trivy version (default: latest) -``` - -### Complete Example - -```yaml -name: Security Scan -on: [push, pull_request] - -jobs: - security: - runs-on: - - ubuntu-latest - - linux_amd64 - steps: - - uses: actions/checkout@v4 - - name: Setup Trivy - uses: your-username/trivy-actions@main/setup-trivy - - name: Scan for vulnerabilities - run: trivy fs . -``` - -## Inputs - -| Input | Description | Required | Default | -| --------- | ----------------------------------------- | -------- | -------- | -| `version` | Trivy version to download (e.g., v0.66.0) | No | `latest` | diff --git a/setup-trivy/action.yaml b/setup-trivy/action.yaml deleted file mode 100644 index b08e9cf..0000000 --- a/setup-trivy/action.yaml +++ /dev/null @@ -1,68 +0,0 @@ -name: "Setup Trivy" -description: "Download and setup Trivy binary for vulnerability scanning" -author: "Gitea Actions" -branding: - icon: "shield" - color: "blue" - -inputs: - version: - description: "Trivy version to download (e.g., latest)" - required: false - default: "latest" - -runs: - using: "composite" - steps: - - shell: bash - id: arch - run: | - set -e - case "$(uname -m)" in - x86_64) - ARCH="64bit" - ;; - aarch64) - ARCH="ARM64" - ;; - esac - echo "ARCH=$ARCH" >> $GITHUB_OUTPUT - - name: Resolve version - shell: bash - id: version - run: | - set -e - if [ "${{ inputs.version }}" = "latest" ]; then - VERSION=$(curl -s https://api.github.com/repos/aquasecurity/trivy/releases/latest | jq -r '.tag_name') - else - VERSION="${{ inputs.version }}" - fi - echo "VERSION=$VERSION" >> $GITHUB_OUTPUT - - name: Cache Trivy binary - id: cache-trivy - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 - with: - path: /usr/local/bin/trivy - key: trivy-${{ steps.version.outputs.version }}-${{ steps.arch.outputs.arch }} - restore-keys: | - trivy-${{ steps.version.outputs.version }}-${{ steps.arch.outputs.arch }} - - name: Download and install Trivy - if: steps.cache-trivy.outputs.cache-hit != 'true' - shell: bash - run: | - set -e - - VERSION="${{ steps.version.outputs.version }}" - - mkdir -p /usr/local/bin - - curl -sL "https://github.com/aquasecurity/trivy/releases/download/${VERSION}/trivy_${VERSION#v}_Linux-${{ steps.arch.outputs.arch }}.tar.gz" -o trivy.tar.gz - tar -xzf trivy.tar.gz - chmod +x trivy - mv trivy /usr/local/bin/ - rm trivy.tar.gz - - - name: Add Trivy to PATH - shell: bash - run: | - echo "/usr/local/bin" >> $GITHUB_PATH