Skip to content

Add daily Trivy scan of fleetdm/fleet built from main#47518

Open
lukeheath wants to merge 3 commits into
mainfrom
add-vuln-scan-main-docker-image
Open

Add daily Trivy scan of fleetdm/fleet built from main#47518
lukeheath wants to merge 3 commits into
mainfrom
add-vuln-scan-main-docker-image

Conversation

@lukeheath

@lukeheath lukeheath commented Jun 12, 2026

Copy link
Copy Markdown
Member

Summary

  • Adds check-vulnerabilities-in-main-docker-image.yml, a daily Trivy scan that builds the fleetdm/fleet image from the current main-branch Dockerfile and scans it for OS-package CVEs.
  • Sibling to check-vulnerabilities-in-released-docker-images.yml, which only scans the 5 most-recently shipped fleetdm/fleet:<version> tags. That leaves a 1-3 week window between an Alpine base image bump landing on main and the next minor cut, during which new OS-package CVEs surface only in external scanners (e.g. Aikido). This workflow closes that window.
  • Concrete motivator: CVE-2026-34182 in openssl 3.5.6-r0 (NVD CVSS 9.1) was disclosed 2026-06-09 and flagged by Aikido against the current fleetdm/fleet build, but the in-repo Trivy daily can't see it because alpine:3.23.4 hasn't shipped in a tagged release yet.

Design

  • Builds locally from tools/fleet-docker/Dockerfile with a placeholder fleet binary (the scan only needs OS layers).
  • Uses --pkg-types=os — Go module CVEs in the real binary are already covered by Dependabot, govulncheck, and Aikido SCA; no point duplicating that work here.
  • Same --severity=CRITICAL threshold and same security/vex/fleet/ VEX suppressions as the released-images workflow, so alert volume stays consistent.
  • Runs at 07:00 UTC, staggered one hour after the released-images workflow at 06:00 UTC.
  • Same Slack webhook (SLACK_G_ORCHESTRATION_WEBHOOK_URL) and same alert format on failure.

Test plan

  • Trigger the workflow manually via workflow_dispatch against this branch.
  • Confirm docker build -f tools/fleet-docker/Dockerfile -t fleetdm/fleet:main-scan tools/fleet-docker/ succeeds with the placeholder binary.
  • Confirm Trivy produces trivy-results-fleet-main.json and a readable table in the job log.
  • On a deliberately broken VEX suppression (or a known CVE), confirm the Slack notification step renders the CVE list correctly.
  • Verify the workflow doesn't post to Slack on workflow_dispatch runs (only scheduled).

Summary by CodeRabbit

  • Chores
    • Added scheduled vulnerability scanning for the main Docker image that detects CRITICAL OS-package issues, fails on critical findings, extracts a concise CVE list, and sends Slack alerts; uses existing VEX data.
    • Improved released-image workflow: deterministic concurrency across runs, refined VEX flag handling for scanning, and stricter download error handling.

Sibling to check-vulnerabilities-in-released-docker-images.yml, which only
scans the most recent 5 shipped releases. That left a 1-3 week blind spot
between an Alpine base image bump landing on main and the next minor cut,
during which new OS-package CVEs (e.g. CVE-2026-34182 in openssl 3.5.6-r0)
go undetected by in-repo CI.

Builds the fleet image from the current main-branch Dockerfile with a
placeholder fleet binary, runs Trivy with --pkg-types=os against it, and
posts to the same Slack webhook on failure.
Copilot AI review requested due to automatic review settings June 12, 2026 15:08
fleet-release
fleet-release previously approved these changes Jun 12, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new GitHub Actions workflow that builds the fleetdm/fleet Docker image from the repo’s current tools/fleet-docker/Dockerfile and runs a daily Trivy scan focused on OS-package CVEs (using Fleet’s existing VEX suppressions), with Slack alerting on scheduled failures.

Changes:

  • Introduces .github/workflows/check-vulnerabilities-in-main-docker-image.yml to run daily at 07:00 UTC (and via workflow_dispatch).
  • Builds a local fleetdm/fleet:main-scan image using a placeholder fleet binary (scan targets OS layers only).
  • Runs Trivy with --pkg-types=os, emits JSON + table output, and posts a Slack alert (scheduled runs only) including an extracted CVE list.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .github/workflows/check-vulnerabilities-in-main-docker-image.yml Outdated
Comment thread .github/workflows/check-vulnerabilities-in-main-docker-image.yml Outdated
Comment thread .github/workflows/check-vulnerabilities-in-main-docker-image.yml Outdated
@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a465a689-fd09-4de6-9b1a-564d6f92228d

📥 Commits

Reviewing files that changed from the base of the PR and between d87cbdd and 27be42b.

📒 Files selected for processing (2)
  • .github/workflows/check-vulnerabilities-in-main-docker-image.yml
  • .github/workflows/check-vulnerabilities-in-released-docker-images.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/check-vulnerabilities-in-main-docker-image.yml

Walkthrough

Adds a GitHub Actions workflow that builds fleetdm/fleet:main-scan from main, enumerates VEX files to construct Trivy flags, runs Trivy to scan for CRITICAL OS package vulnerabilities (writing JSON and a table), parses and deduplicates CVEs from Trivy JSON on failure, exposes a formatted cve_list, and sends a Slack incoming-webhook notification when a scheduled cron run fails.

Possibly related PRs

  • fleetdm/fleet#45825: Adds VEX files under security/vex/fleetctl/ which the new workflow will consume to filter reported OS CVEs.
  • fleetdm/fleet#46186: Adds VEX entries under security/vex/fleet/ for Docker CVEs that this Trivy scan will apply.
  • fleetdm/fleet#45232: Implements extract-and-format CVE extraction plus Slack “Detected CVEs” behavior similar to this workflow’s results processing and notification.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: adding a daily Trivy vulnerability scan for the fleetdm/fleet Docker image built from the main branch.
Description check ✅ Passed The PR description is comprehensive and well-structured with clear sections for Summary, Design, and Test plan, covering the motivation, implementation details, and testing approach.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch add-vuln-scan-main-docker-image

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
.github/workflows/check-vulnerabilities-in-main-docker-image.yml (1)

49-54: 💤 Low value

Consider simplifying the VEX file enumeration.

The current shell pipeline works but could be more readable.

♻️ Proposed simplification
       - name: List fleet VEX files
         id: generate_fleet_vex_files
         run: |
-          VEX_FILES=$(ls -1 ./security/vex/fleet/ | while IFS= read -r line; do echo "./security/vex/fleet/$line"; done | tr '\n' ',' | sed 's/.$//')
+          VEX_FILES=$(find ./security/vex/fleet/ -type f -printf './security/vex/fleet/%f,' | sed 's/,$//')
           echo $VEX_FILES
           echo "FLEET_VEX_FILES=$VEX_FILES" >> $GITHUB_OUTPUT

Alternatively, using a simpler approach:

       - name: List fleet VEX files
         id: generate_fleet_vex_files
         run: |
-          VEX_FILES=$(ls -1 ./security/vex/fleet/ | while IFS= read -r line; do echo "./security/vex/fleet/$line"; done | tr '\n' ',' | sed 's/.$//')
+          VEX_FILES=$(ls -1 ./security/vex/fleet/*.vex.json | tr '\n' ',' | sed 's/,$//')
           echo $VEX_FILES
           echo "FLEET_VEX_FILES=$VEX_FILES" >> $GITHUB_OUTPUT
🤖 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/check-vulnerabilities-in-main-docker-image.yml around
lines 49 - 54, Replace the long pipeline that builds VEX_FILES in the step with
a simpler glob + printf approach: use the step id generate_fleet_vex_files and
variable VEX_FILES to collect files via something like VEX_FILES=$(printf '%s,'
./security/vex/fleet/* | sed 's/,$//') (or use IFS=,; echo
./security/vex/fleet/*) to produce a comma-separated list, then keep the echo
"FLEET_VEX_FILES=$VEX_FILES" >> $GITHUB_OUTPUT line to export it.
🤖 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/workflows/check-vulnerabilities-in-main-docker-image.yml:
- Around line 36-39: The workflow pins actions/checkout to an old v3 SHA
(actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9); update the uses
declaration for actions/checkout to the v4 release (e.g., actions/checkout@v4 or
the same v4 SHA used elsewhere such as
actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683) by replacing the
current uses value in the Checkout step so this workflow aligns with other
workflows and gets the v4 fixes/improvements.
- Around line 74-81: The Trivy invocation is passing multiple local VEX files as
one comma-separated value to the --vex flag (use the output from
generate_fleet_vex_files.outputs.FLEET_VEX_FILES), but Trivy requires a separate
--vex flag per source; update the trivy command in the workflow so the value of
FLEET_VEX_FILES is expanded into repeated --vex arguments (one --vex per file)
before calling ./trivy image (e.g., build the flags by splitting the
FLEET_VEX_FILES output and prefixing each with "--vex" or iterate over the list
and call trivy with multiple --vex entries) so that --vex is not given a
comma-separated list as a single argument.

---

Nitpick comments:
In @.github/workflows/check-vulnerabilities-in-main-docker-image.yml:
- Around line 49-54: Replace the long pipeline that builds VEX_FILES in the step
with a simpler glob + printf approach: use the step id generate_fleet_vex_files
and variable VEX_FILES to collect files via something like VEX_FILES=$(printf
'%s,' ./security/vex/fleet/* | sed 's/,$//') (or use IFS=,; echo
./security/vex/fleet/*) to produce a comma-separated list, then keep the echo
"FLEET_VEX_FILES=$VEX_FILES" >> $GITHUB_OUTPUT line to export it.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: aff49d54-0927-4845-a129-8092e7fb3eed

📥 Commits

Reviewing files that changed from the base of the PR and between e4a02af and d737d93.

📒 Files selected for processing (1)
  • .github/workflows/check-vulnerabilities-in-main-docker-image.yml

Comment thread .github/workflows/check-vulnerabilities-in-main-docker-image.yml
Comment thread .github/workflows/check-vulnerabilities-in-main-docker-image.yml
- Bump actions/checkout from v3.5.3 to v4.2.2 (matches the SHA used by the
  rest of the repo).
- Pass VEX files as repeated --vex= flags instead of one comma-separated
  value. Trivy treats a comma-separated --vex value as a single path, so
  only the first listed file (or none) was being applied.
fleet-release
fleet-release previously approved these changes Jun 12, 2026
@lukeheath

Copy link
Copy Markdown
Member Author

Addressed CodeRabbit's two actionable findings in d87cbdd:

  • actions/checkout v3 → v4 (line 36-39): bumped to actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2, the SHA already used by the rest of the repo.
  • Trivy --vex formatting (line 74-81): the workflow was passing all VEX paths as a single comma-separated value, which Trivy interprets as one path. Changed the List fleet VEX files step to emit pre-formatted --vex=... tokens (one per file) and inlined them unquoted into the trivy invocation so bash word-splits them into separate flags.

Skipped the nitpick (line 49-54) on simplifying the ls | while | tr | sed pipeline. The proposed find -printf form isn't portable across all runners and the alternative ls *.vex.json form changes the produced flag construction. The current pipeline is consistent with the sibling check-vulnerabilities-in-released-docker-images.yml and not worth diverging here for a style nit.

The sibling workflow has the same v3 checkout pin and the same comma-separated --vex pattern. Filing a follow-up to fix it there separately to keep this PR scoped.

Main workflow (this PR):
- Concurrency group keyed on github.ref instead of head_ref||run_id so the
  scheduled and dispatched runs actually share a group and cancel-in-progress
  works as the comment claims.
- Renamed step "Build fleet docker image from main" to "Build fleet docker
  image" because workflow_dispatch builds from the dispatched ref, not main.
- Hardened the trivy curl: -fsSL plus --retry 3 so an HTTP error fails the
  step instead of producing a non-tarball body that breaks tar later.

Released-images workflow has the same issues; applying the same fixes plus
the checkout-v4 and --vex-multiple-flags fixes from the previous commit.
@lukeheath

Copy link
Copy Markdown
Member Author

Addressed the Copilot review (4486832152) in 27be42b:

  • Concurrency run_id fallback (line 14-17): keyed the group on github.ref (always defined: refs/heads/<default_branch> on schedule, the dispatched ref on workflow_dispatch) so scheduled runs actually share a group and cancel-in-progress does what the comment claims.
  • "Build fleet docker image from main" step name (line 41): renamed to "Build fleet docker image" since workflow_dispatch runs build from the dispatched ref, not main.
  • curl -L without --fail (line 65): switched to curl -fsSL --retry 3 so HTTP errors fail the step instead of producing a non-tarball body that breaks tar later.

Replicated all the fixes from this PR (checkout v3→v4, --vex as repeated flags, and the three Copilot items above) to the sibling check-vulnerabilities-in-released-docker-images.yml since that workflow had the same issues. Both scans now share a consistent pattern.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants