From f065adad50d7765ad549889a48f10c18288b9b35 Mon Sep 17 00:00:00 2001 From: support Date: Thu, 15 Oct 2026 21:25:06 +0200 Subject: [PATCH] Add Trivy security scan workflow and README badge Scans the repository (NuGet, npm, Dockerfile, secrets) and the built Docker image with Trivy. Every finding is uploaded as SARIF to code scanning; the job fails only on fixable HIGH and CRITICAL findings, so the badge shows whether a known fix is waiting to be applied. A weekly run keeps the badge current as new CVEs are published. --- .github/workflows/trivy.yml | 129 ++++++++++++++++++++++++++++++++++++ README.md | 1 + 2 files changed, 130 insertions(+) create mode 100644 .github/workflows/trivy.yml diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml new file mode 100644 index 000000000..f778dff7d --- /dev/null +++ b/.github/workflows/trivy.yml @@ -0,0 +1,129 @@ +name: Trivy + +on: + push: + branches: [ "main", "develop" ] + pull_request: + branches: [ "develop" ] + # New CVEs land in the database without any commit here, so the badge + # is refreshed against the current state of develop once a week. + schedule: + - cron: '0 4 * * 1' + workflow_dispatch: + +# Nothing by default; each job asks for exactly what it needs. +permissions: {} + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + IMAGE: grandnode2:trivy + +jobs: + # NuGet (Directory.Packages.props) and npm (package-lock.json) dependencies, + # Dockerfile misconfiguration and committed secrets. + repository: + name: Scan repository + runs-on: ubuntu-latest + + permissions: + contents: read + security-events: write # upload SARIF to code scanning + + steps: + - name: Checkout + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + + # Every finding goes to the Security tab; this step never fails the job. + - name: Trivy filesystem scan (SARIF) + uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 + with: + scan-type: fs + scan-ref: . + scanners: vuln,misconfig,secret + format: sarif + output: trivy-fs.sarif + + # A pull request from a fork gets a read-only token and cannot upload. + - name: Upload SARIF + if: ${{ !cancelled() && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) }} + uses: github/codeql-action/upload-sarif@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3 + with: + sarif_file: trivy-fs.sarif + category: trivy-fs + + # The gate behind the badge: fixable HIGH and CRITICAL findings only. + - name: Trivy filesystem gate + uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 + with: + scan-type: fs + scan-ref: . + scanners: vuln,misconfig,secret + severity: HIGH,CRITICAL + ignore-unfixed: true + format: table + exit-code: '1' + skip-setup-trivy: true + + # The image as the Dockerfile builds it: base OS packages plus the published app. + image: + name: Scan Docker image + runs-on: ubuntu-latest + + permissions: + contents: read + security-events: write # upload SARIF to code scanning + + steps: + - name: Checkout + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1 + + - name: Build Docker image + uses: docker/build-push-action@c3c9e263c25d99ce0380d002d59b67737d91b0dc # v7.4.0 + with: + context: . + load: true + push: false + build-args: | + GIT_COMMIT=${{ github.sha }} + GIT_BRANCH=${{ github.ref_name }} + tags: ${{ env.IMAGE }} + cache-from: type=gha + cache-to: type=gha,mode=max + + - name: Trivy image scan (SARIF) + uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 + with: + scan-type: image + image-ref: ${{ env.IMAGE }} + scanners: vuln,secret + format: sarif + output: trivy-image.sarif + + - name: Upload SARIF + if: ${{ !cancelled() && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) }} + uses: github/codeql-action/upload-sarif@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3 + with: + sarif_file: trivy-image.sarif + category: trivy-image + + - name: Trivy image gate + uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 + with: + scan-type: image + image-ref: ${{ env.IMAGE }} + scanners: vuln,secret + severity: HIGH,CRITICAL + ignore-unfixed: true + format: table + exit-code: '1' + skip-setup-trivy: true diff --git a/README.md b/README.md index 4bc782667..409f0d030 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,7 @@ [![Tests on Linux, macOS and Windows](https://github.com/grandnode/grandnode2/actions/workflows/aspnetcore.yml/badge.svg)](https://github.com/grandnode/grandnode2/actions/workflows/aspnetcore.yml) [![Docker Image CI](https://github.com/grandnode/grandnode2/actions/workflows/docker-image.yml/badge.svg)](https://github.com/grandnode/grandnode2/actions/workflows/docker-image.yml) [![CodeQL Advanced](https://github.com/grandnode/grandnode2/actions/workflows/codeql.yml/badge.svg)](https://github.com/grandnode/grandnode2/actions/workflows/codeql.yml) +[![Trivy](https://github.com/grandnode/grandnode2/actions/workflows/trivy.yml/badge.svg?branch=develop)](https://github.com/grandnode/grandnode2/actions/workflows/trivy.yml)