Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
14 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 106 additions & 0 deletions .github/steps/trivy/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
name: "Vulnerability Scan"
description: "Trivy PR security scans. scan: code = repo dependencies (HIGH/CRITICAL) + Dockerfile base images (CRITICAL), image = image built in the pipeline (HIGH/CRITICAL). Each scan uploads its TSV report as an artifact"

inputs:
scan:
description: "code | image"
required: true
maven-token:
description: "Token for internal GitHub Packages: Maven resolution (scan: code) and docker build secret (scan: image)"
required: false
default: ${{ github.token }}
image-name:
description: "Service name from the matrix; used in the artifact name"
required: false
path:
description: "Directory to scan (scan: code), e.g. a single service; defaults to the whole repo"
required: false
default: "."
skip-dirs:
description: "Comma-separated directories to exclude from the code scan (e.g. service dirs already scanned by the matrix)"
required: false
default: ""
dockerfile:
description: "Path to the service Dockerfile (scan: image)"
required: false
context:
description: "Docker build context (scan: image)"
required: false

runs:
using: composite
steps:
- name: Install Trivy
uses: aquasecurity/setup-trivy@v0.3.1
with:
version: v0.73.0
cache: true

- name: Scan dependencies and Dockerfile base images
if: inputs.scan == 'code'
shell: bash
env:
GITHUB_TOKEN: ${{ inputs.maven-token }}
GITHUB_ACTOR: ${{ github.actor }}
run: |
set -euo pipefail
dir="${{ inputs.path }}"
if [ -f "$dir/pom.xml" ]; then # warm ~/.m2 via Google's Central mirror so trivy sees parent-managed versions
echo '<settings><mirrors><mirror><id>google-central</id><url>https://maven-central.storage-download.googleapis.com/maven2/</url><mirrorOf>central</mirrorOf></mirror></mirrors></settings>' > /tmp/mirror.xml
mvn -B -q -fn -DskipTests -gs /tmp/mirror.xml -f "$dir/pom.xml" $([ -f .mvn/settings.xml ] && echo '-s .mvn/settings.xml') dependency:go-offline | tee /tmp/mvn.log || true
! grep -q '\[ERROR\]' /tmp/mvn.log || echo "::warning::Some Maven dependencies could not be resolved; scan depth may be reduced"
fi
skip="${{ inputs.skip-dirs }}"
targs=(--no-progress --scanners vuln --severity HIGH,CRITICAL --ignore-unfixed --offline-scan --format json)
[ -n "$skip" ] && targs+=(--skip-dirs "$skip")
trivy fs "${targs[@]}" "$dir" |
jq -r '.Results[]? as $r | $r.Vulnerabilities[]? | [.Severity, .PkgName, .InstalledVersion, (.FixedVersion // "-"), .VulnerabilityID, $r.Target] | @tsv' | sort -u > "trivy-${GITHUB_REPOSITORY##*/}-code-report.tsv"

out="trivy-${GITHUB_REPOSITORY##*/}-docker-report.tsv"; : > "$out"
fargs=(-name 'Dockerfile*' -not -path '*/.git/*' -not -path '*/node_modules/*')
[ -n "$skip" ] && for d in ${skip//,/ }; do fargs+=(-not -path "*/${d}/*" -not -path "${d}/*"); done
find "$dir" "${fargs[@]}" -print0 |
xargs -0 -r awk 'toupper($1)=="FROM" {i=$2; if (i ~ /^--/) i=$3; print i; if (toupper($3)=="AS") print "~"$4; if (toupper($4)=="AS") print "~"$5}' | sort -u > /tmp/from.txt
for img in $(grep -v '^~' /tmp/from.txt); do
[ "$img" = scratch ] && continue
case "$img" in *'$'*) echo "::warning::Skipping base image with unresolved variable: ${img}"; continue ;; esac
grep -qxF "~$img" /tmp/from.txt && continue
trivy image --no-progress --scanners vuln --severity CRITICAL --ignore-unfixed --format json "$img" |
jq -r --arg img "$img" '.Results[]? as $r | $r.Vulnerabilities[]? | [.Severity, .PkgName, .InstalledVersion, (.FixedVersion // "-"), .VulnerabilityID, $img] | @tsv' >> "$out" ||
echo "::warning::Base image ${img} could not be scanned (pull/scan error); it was NOT checked"
done
sort -u "$out" -o "$out"
find . -maxdepth 1 -name 'trivy-*.tsv' -empty -delete

- name: Scan built image
if: inputs.scan == 'image'
shell: bash
env:
GITHUB_TOKEN: ${{ inputs.maven-token }}
GITHUB_ACTOR: ${{ github.actor }}
run: |
set -euo pipefail
docker buildx build --platform linux/amd64 --secret id=GITHUB_TOKEN,env=GITHUB_TOKEN --build-arg GITHUB_ACTOR="$GITHUB_ACTOR" \
-f "${{ inputs.dockerfile }}" --output type=oci,dest=/tmp/image.tar "${{ inputs.context }}"
out="trivy-${GITHUB_REPOSITORY##*/}-image-report-${{ inputs.image-name }}.tsv"
trivy image --no-progress --scanners vuln --severity HIGH,CRITICAL --ignore-unfixed --input /tmp/image.tar --format json |
jq -r '.Results[]? as $r | $r.Vulnerabilities[]? | [.Severity, .PkgName, .InstalledVersion, (.FixedVersion // "-"), .VulnerabilityID, $r.Target] | @tsv' | sort -u > "$out"
find . -maxdepth 1 -name 'trivy-*.tsv' -empty -delete

- name: Upload report
uses: actions/upload-artifact@v4
with:
name: ${{ inputs.scan == 'code' && (inputs.image-name && format('scan_code-{0}', inputs.image-name) || 'scan_code') || format('scan_image-{0}', inputs.image-name) }}
path: trivy-*.tsv
if-no-files-found: ignore

- name: Evaluate
shell: bash
env:
ARTIFACT: ${{ inputs.scan == 'code' && 'scan_code' || 'scan_image' }}
run: |
set -euo pipefail
files=$(ls trivy-*.tsv 2>/dev/null) || { echo "No vulnerabilities found."; exit 0; }
column -t -s "$(printf '\t')" $files
echo "::error::Trivy found $(cut -f1,2,5 $files | sort -u | wc -l | tr -d ' ') unique HIGH/CRITICAL vulnerabilities ($(cat $files | wc -l | tr -d ' ') occurrences across modules) — full report in the ${ARTIFACT} artifact"
exit 1
37 changes: 33 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,18 +64,18 @@ jobs:
- name: Setup MSBuild
if: runner.os == 'Windows'
uses: microsoft/setup-msbuild@v2

- name: Setup Visual Studio Build Tools
if: runner.os == 'Windows'
uses: ilammy/msvc-dev-cmd@v1
with:
arch: ${{ matrix.os_arch }}
arch: ${{ matrix.os_arch }}

- name: Install macOS Dependencies
if: runner.os == 'macOS'
run: brew install openssl jpeg zlib
shell: bash

- name: Build MeshAgent for Windows ${{ matrix.os_arch }} with MSBuild
if: matrix.os == 'windows-latest'
run: msbuild MeshAgent-2022.sln -p:Configuration=Release -p:Platform=${{ matrix.os_arch }} -p:WindowsTargetPlatformVersion=10.0.26100.0
Expand All @@ -86,4 +86,33 @@ jobs:
run: |
echo "Building MeshAgent for macOS ${{ matrix.os_arch }}"
make macos ARCHID=${{ matrix.archid }}
shell: bash
shell: bash

scan:
name: "Scan"
runs-on: ubuntu-latest
permissions:
contents: read
packages: read
if: github.event_name == 'pull_request' && github.event.pull_request.state == 'open' && !github.event.pull_request.draft
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
persist-credentials: false

- name: Scan code
uses: ./.github/steps/trivy
with:
scan: code

all-checks:
name: "All Checks"
needs: [build_client]
runs-on: ubuntu-latest
if: always()
steps:
- if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}
run: exit 1
- run: echo "All checks passed"
3 changes: 3 additions & 0 deletions .trivyignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Vulnerabilities to skip in the Trivy scan: one CVE/GHSA id per line, e.g.:
#
# CVE-2026-12345