ci: add Trivy security scan to PR pipeline - #63
Conversation
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughThe pull request adds a composite Trivy action. The action resolves Maven dependencies, scans repository files and Dockerfile base images, aggregates findings, and fails on unfixed HIGH or CRITICAL vulnerabilities. A pull-request workflow job runs the scan and gates ChangesTrivy security scanning
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant PullRequest
participant trivy_scan
participant TrivyAction
participant Maven
participant Trivy
PullRequest->>trivy_scan: trigger eligible pull request job
trivy_scan->>TrivyAction: run shared scan action
TrivyAction->>Maven: resolve project dependencies
TrivyAction->>Trivy: scan files and Dockerfile base images
Trivy-->>TrivyAction: return vulnerability reports
TrivyAction-->>trivy_scan: return scan status
trivy_scan-->>PullRequest: publish job result
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/steps/trivy/action.yml:
- Around line 62-67: Update the trivy image-scan failure branch in the loop
around the `trivy image` command to exit nonzero when scanning a concrete image
fails, instead of always echoing and continuing. Preserve the existing skip
behavior for `scratch` and unresolved image variables by ensuring those cases
are filtered before this failure path.
- Around line 13-17: Update the Install Trivy step’s uses reference from the
mutable aquasecurity/setup-trivy@v0.3.1 tag to a reviewed, immutable
40-character commit SHA, keeping the existing version and cache inputs
unchanged.
- Around line 37-39: Update the Maven arguments in the dependency-resolution
step to remove the -fn flag, and make the mvn invocation propagate
dependency:go-offline failures instead of converting them into a warning.
Preserve the existing arguments and optional .mvn/settings.xml handling.
In @.github/workflows/test.yml:
- Around line 45-56: Update the trivy_scan workflow so fork pull requests never
run tokenized Maven dependency resolution: disable credential persistence in the
Checkout step and remove or conditionally skip the Trivy composite action’s
Maven resolution for fork-originated pull requests, while preserving it for
same-repository pull requests as appropriate.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 241c476c-3c1b-40af-99ff-2237a53055a1
📒 Files selected for processing (3)
.github/steps/trivy/action.yml.github/workflows/test.yml.trivyignore
| - name: Install Trivy | ||
| uses: aquasecurity/setup-trivy@v0.3.1 | ||
| with: | ||
| version: v0.73.0 | ||
| cache: true |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
ref="$(awk '/uses: aquasecurity\/setup-trivy@/ {print $2}' .github/steps/trivy/action.yml)"
[[ "$ref" =~ ^aquasecurity/setup-trivy@[0-9a-f]{40}$ ]]Repository: flamingo-stack/meshcentral
Length of output: 164
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "## action.yml relevant lines"
sed -n '1,45p' .github/steps/trivy/action.yml
echo
echo "## current Trivy pin"
ref="$(awk '/uses: aquasecurity\/setup-trivy@/ {print $2}' .github/steps/trivy/action.yml)"
printf 'pin=%s\n' "$ref"
[[ "$ref" =~ ^aquasecurity/setup-trivy@[0-9a-f]{40}$ ]]
exit_code=$?
echo "matches_40_char_sha=$exit_code"Repository: flamingo-stack/meshcentral
Length of output: 2174
🌐 Web query:
aquasecurity setup-trivy advisory GHSA-69fq-xp46-6x23 March 2026 full commit SHA pin recommendation
💡 Result:
In response to the supply chain compromise identified as GHSA-69fq-xp46-6x23 (CVE-2026-33634) in March 2026, where a threat actor force-pushed malicious code to all existing tags (v0.2.0–v0.2.6) of the aquasecurity/setup-trivy GitHub Action, users are strongly advised to pin to a verified, safe commit SHA [1][2][3]. The specific commit SHA identified as the safe version for setup-trivy v0.2.6 following the incident is 3fb12ec12f41e471780db15c232d5dd185dcb514 [4][5]. Security best practices for using GitHub Actions, particularly following this incident, include: 1. Pinning to full, immutable commit SHA hashes rather than relying on mutable version tags (e.g., v0.2.6) to prevent similar supply chain attacks where tags are overwritten [6][3]. 2. Treating any pipeline secrets used during the exposure window (March 19, 2026, 17:43 UTC to approximately March 19, 2026, 21:44 UTC for setup-trivy) as compromised and rotating them immediately [1][4][2]. For additional context, aquasecurity restored setup-trivy v0.2.6 with safe content after the incident, but because the attacker force-pushed to the tags, users who had previously cached or pulled the malicious version of v0.2.6 must ensure they update to the corrected SHA [1][2].
Citations:
- 1: GHSA-69fq-xp46-6x23
- 2: https://github.com/aquasecurity/trivy/security/advisories/GHSA-69fq-xp46-6x23?pubDate=20260526
- 3: https://www.wiz.io/vulnerability-database/cve/ghsa-69fq-xp46-6x23
- 4: Trivy Security incident 2026-03-19 aquasecurity/trivy#10425
- 5: fix(1.33): pin setup-trivy to v0.2.6 by SHA (GHSA-69fq-xp46-6x23) canonical/microk8s#5435
- 6: https://nvd.nist.gov/vuln/detail/CVE-2026-33634
Pin aquasecurity/setup-trivy to a full commit SHA.
The pin aquasecurity/setup-trivy@v0.3.1 uses a mutable third-party action tag. A changed tag can execute code with the Maven token. Use a reviewed 40-character commit SHA instead.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/steps/trivy/action.yml around lines 13 - 17, Update the Install
Trivy step’s uses reference from the mutable aquasecurity/setup-trivy@v0.3.1 tag
to a reviewed, immutable 40-character commit SHA, keeping the existing version
and cache inputs unchanged.
| margs=(-B -q -fn -DskipTests -gs /tmp/central-mirror.xml dependency:go-offline) | ||
| [ -f .mvn/settings.xml ] && margs+=(-s .mvn/settings.xml) | ||
| mvn "${margs[@]}" || echo "::warning::Maven dependency resolution incomplete; pom.xml scan depth may be reduced" |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
mvn --help | grep -F -- '--fail-never'Repository: flamingo-stack/meshcentral
Length of output: 201
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Locate action file and surrounding content"
if [ -f .github/steps/trivy/action.yml ]; then
nl -ba .github/steps/trivy/action.yml | sed -n '1,120p'
else
echo ".github/steps/trivy/action.yml not found"
fi
echo
echo "Search for action usage and related Trivy step files"
rg -n "trivy|dependency:go-offline|-fn|--fail-never|go-offline" .github pom.xml 2>/dev/null || trueRepository: flamingo-stack/meshcentral
Length of output: 247
🌐 Web query:
Maven fail-never option documentation "--fail-never" "never fail the build"
💡 Result:
The Maven --fail-never (or -fn) option is a command-line flag that instructs Maven to never fail the build, regardless of the project's result [1][2]. Key characteristics of this option include: - Behavior: When this option is used, even if individual modules or tasks within a multi-module project encounter errors or failures, Maven will continue processing the remaining modules in the reactor and report the overall build as a success [3][4][5]. - Usage: It is primarily intended for use in multi-module builds where you want to ensure all modules are processed or checked, regardless of whether some fail [2][5]. - Distinction from Test Failures: It is important to distinguish --fail-never from configuration properties like -Dmaven.test.failure.ignore=true [6]. While --fail-never influences the lifecycle behavior of the reactor (preventing build-level failure), it does not specifically silence test failures; individual tests may still report as failures in the logs, but the overall build status remains success [6][5]. This option is often utilized in continuous integration environments where you want to collect results from all modules even if one encounters an issue during the process [2][5].
Citations:
- 1: https://maven.apache.org/ref/3.9.16/maven-embedder/cli.html
- 2: https://www.sonatype.com/maven-complete-reference/running-maven
- 3: https://svn-eu.apache.org/repos/asf/maven/website/content/guides/mini/guide-multiple-subprojects-4.html
- 4: https://maven.apache.org/guides/mini/guide-multiple-subprojects-4.html
- 5: https://blog.spree.de/2010/06/07/mastering-the-maven-command-line-managing-failures/
- 6: https://stackoverflow.com/questions/22846430/two-optional-arguments-in-maven-command-fn-v-s-dmaven-test-failure-ignore
🏁 Script executed:
#!/bin/bash
set -u
echo "Locate action file and surrounding content"
if [ -f .github/steps/trivy/action.yml ]; then
awk '{printf "%6d\t%s\n", NR, $0}' .github/steps/trivy/action.yml | sed -n '1,140p'
else
echo ".github/steps/trivy/action.yml not found"
fi
echo
echo "Search for action usage and related Trivy step files"
rg -n "trivy|dependency:go-offline|-fn|--fail-never|go-offline" .github pom.xml 2>/dev/null || true
echo
echo "Shell check: whether current maven command exists"
command -v mvn || trueRepository: flamingo-stack/meshcentral
Length of output: 6332
Fail the gate when Maven dependency resolution fails.
With set -euo pipefail, mvn should fail the step on dependency:go-offline errors, but -fn forces Maven to return success. Remove -fn and do not downgrade mvn failures to warnings.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/steps/trivy/action.yml around lines 37 - 39, Update the Maven
arguments in the dependency-resolution step to remove the -fn flag, and make the
mvn invocation propagate dependency:go-offline failures instead of converting
them into a warning. Preserve the existing arguments and optional
.mvn/settings.xml handling.
| if trivy image --scanners vuln --severity HIGH,CRITICAL --ignore-unfixed --format json -o img.json "$img"; then | ||
| jq --arg s "$img" '.Results = ((.Results // []) | map(. + {ScanSrc: ("image " + $s)}))' img.json > img2.json | ||
| jq -s '{Results: (.[0].Results + (.[1].Results // []))}' combined.json img2.json > tmp.json && mv tmp.json combined.json | ||
| else | ||
| echo "skip ${img}" | ||
| fi |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Fail closed for a concrete base image that cannot be scanned.
Line 66 suppresses every image-scan failure. A pull request can change FROM to an unreachable concrete image and receive a passing security gate when the filesystem scan is clean. Keep the existing skips for scratch and unresolved variables, but exit nonzero after a trivy image failure.
Proposed fix
else
- echo "skip ${img}"
+ echo "::error::Unable to scan base image ${img}"
+ exit 1
fi📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if trivy image --scanners vuln --severity HIGH,CRITICAL --ignore-unfixed --format json -o img.json "$img"; then | |
| jq --arg s "$img" '.Results = ((.Results // []) | map(. + {ScanSrc: ("image " + $s)}))' img.json > img2.json | |
| jq -s '{Results: (.[0].Results + (.[1].Results // []))}' combined.json img2.json > tmp.json && mv tmp.json combined.json | |
| else | |
| echo "skip ${img}" | |
| fi | |
| if trivy image --scanners vuln --severity HIGH,CRITICAL --ignore-unfixed --format json -o img.json "$img"; then | |
| jq --arg s "$img" '.Results = ((.Results // []) | map(. + {ScanSrc: ("image " + $s)}))' img.json > img2.json | |
| jq -s '{Results: (.[0].Results + (.[1].Results // []))}' combined.json img2.json > tmp.json && mv tmp.json combined.json | |
| else | |
| echo "::error::Unable to scan base image ${img}" | |
| exit 1 | |
| fi |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/steps/trivy/action.yml around lines 62 - 67, Update the trivy
image-scan failure branch in the loop around the `trivy image` command to exit
nonzero when scanning a concrete image fails, instead of always echoing and
continuing. Preserve the existing skip behavior for `scratch` and unresolved
image variables by ensuring those cases are filtered before this failure path.
| 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 }} | ||
|
|
||
| - name: Trivy scan (fs + base images) | ||
| uses: ./.github/steps/trivy |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
rg -n -C 4 \
'head\.repo|persist-credentials|maven-token|GITHUB_TOKEN|dependency:go-offline' \
.github/workflows/test.yml .github/steps/trivy/action.ymlRepository: flamingo-stack/meshcentral
Length of output: 2778
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== workflow relevant lines =="
sed -n '1,110p' .github/workflows/test.yml | cat -n
echo
echo "== trivy action relevant lines =="
sed -n '1,80p' .github/steps/trivy/action.yml | cat -n
echo
echo "== workflow references to head repo / forks / persist-credentials =="
rg -n 'pull_request|fork|persist-credentials|maven-token|GITHUB_TOKEN|actions/checkout|trivy' .github/workflows/test.yml .github/steps/trivy/action.ymlRepository: flamingo-stack/meshcentral
Length of output: 10873
Do not run Maven dependency resolution for fork pull requests.
The trivy_scan job runs for all open non-draft pull requests and checks out the pull request head. actions/checkout stores credentials by default, and the Trivy composite action exports GITHUB_TOKEN to Maven during dependency:go-offline. Maven can load pull-request-controlled build configuration such as .mvn/extensions.xml, so a fork PR could use that configuration to read the token. Set persist-credentials: false, remove Maven resolution from fork workflows, or scope tokenized Maven resolution to same-repository pull requests.
🧰 Tools
🪛 zizmor (1.28.0)
[warning] 50-53: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/test.yml around lines 45 - 56, Update the trivy_scan
workflow so fork pull requests never run tokenized Maven dependency resolution:
disable credential persistence in the Checkout step and remove or conditionally
skip the Trivy composite action’s Maven resolution for fork-originated pull
requests, while preserving it for same-repository pull requests as appropriate.
Source: Linters/SAST tools
…s for skipped scans
Adds a Trivy-based PR security gate:
Summary by CodeRabbit