Skip to content

Add OpenVEX report generation via govulncheck#9767

Merged
openshift-merge-bot[bot] merged 1 commit into
cri-o:mainfrom
saschagrunert:vex-support
Feb 18, 2026
Merged

Add OpenVEX report generation via govulncheck#9767
openshift-merge-bot[bot] merged 1 commit into
cri-o:mainfrom
saschagrunert:vex-support

Conversation

@saschagrunert

@saschagrunert saschagrunert commented Feb 16, 2026

Copy link
Copy Markdown
Member

What type of PR is this?

/kind feature

What this PR does / why we need it:

Adds project-level VEX (Vulnerability Exploitability eXchange) support:

  • Extends hack/govulncheck.sh to generate an OpenVEX document
  • Adds make vex target
  • Adds VEX download link and verification instructions to release notes
  • Documents VEX in SECURITY.md

Which issue(s) this PR fixes:

Fixes #9104

Special notes for your reviewer:

Requires a companion PR in cri-o/packaging to generate, sign, and
upload the VEX file during the release process:
cri-o/packaging#339

Does this PR introduce a user-facing change?

Add OpenVEX vulnerability report generation for releases

Summary by CodeRabbit

  • New Features

    • Added a build target to generate OpenVEX reports so users can produce VEX artifacts locally.
  • Documentation

    • Expanded security docs with OpenVEX details, generation and verification guidance.
    • Updated release notes templates to include OpenVEX sections and verification instructions.
  • Chores

    • CI now preserves and uploads generated OpenVEX artifacts as part of security workflows.

@openshift-ci openshift-ci Bot added do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. release-note Denotes a PR that will be considered when it comes time to generate release notes. dco-signoff: yes Indicates the PR's author has DCO signed all their commits. kind/feature Categorizes issue or PR as related to a new feature. labels Feb 16, 2026
@openshift-ci openshift-ci Bot requested review from klihub and littlejawa February 16, 2026 16:17
@coderabbitai

coderabbitai Bot commented Feb 16, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Adds OpenVEX generation and publishing: a new make vex target, govulncheck script updates to emit an OpenVEX report and VEX-only mode, SECURITY.md documentation, CI steps to upload the OpenVEX artifact, and release-notes template updates referencing and verifying the OpenVEX artifact.

Changes

Cohort / File(s) Summary
Build targets
Makefile
Adds .PHONY: vex and vex target that runs VEX_ONLY=true ./hack/govulncheck.sh to generate the OpenVEX artifact.
Vulnerability check script
hack/govulncheck.sh
Emits OpenVEX to build/cri-o.openvex.json, adds VEX_ONLY early-exit, produces a separate JSON vuln report, and distinguishes stdlib vs module vulns for exit codes.
Documentation
SECURITY.md
Adds OpenVEX section describing format, generation via govulncheck, artifact path, and local make vex usage.
CI workflow
.github/workflows/test.yml
security-checks now uploads build/cri-o.openvex.json; new vex-upload job downloads that artifact and uploads it to Cloud Storage (cri-o/artifacts).
Release notes
scripts/release-notes/release_notes.go
Adds OpenVEX download link and cosign verify blocks to the release template and extends template arguments for bundle/version placeholders.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Dev as Developer
  participant Make as Makefile
  participant Script as hack/govulncheck.sh
  participant GV as govulncheck
  participant CI as GitHub Actions
  participant Store as Cloud Storage

  Dev->>Make: make vex
  Make->>Script: run with VEX_ONLY=true
  Script->>GV: govulncheck -format openvex
  GV-->>Script: build/cri-o.openvex.json
  Script->>Make: emit path (build/cri-o.openvex.json)
  Note over CI,Store: On main/release/tag
  CI->>CI: run security-checks (upload vex artifact)
  CI->>Store: vex-upload job uploads artifact to cri-o/artifacts
  Store-->>CI: stored artifact
  CI->>Script: release-notes include OpenVEX link & cosign verification
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • mrunalp
  • littlejawa

Poem

🐇 I hopped a patch through code and log,
OpenVEX now sleeps in build and fog,
govulncheck sings where truths are vexed,
CI packs and signs the little text,
A rabbit smiles — the artifacts indexed.

🚥 Pre-merge checks | ✅ 5 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed The PR fully implements VEX integration into CRI-O's processes including generation via govulncheck, documentation, release notes, and CI/CD automation, meeting all objectives from issue #9104.
Out of Scope Changes check ✅ Passed All changes directly support VEX generation and distribution: govulncheck script, Makefile target, documentation, release notes templates, and CI/CD automation are all in-scope.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into main
Title check ✅ Passed The title accurately describes the main change: adding OpenVEX report generation functionality via the govulncheck tool, which is reflected across multiple files (Makefile, script, documentation, and CI/CD).

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

@openshift-ci

openshift-ci Bot commented Feb 16, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: saschagrunert

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci openshift-ci Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Feb 16, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
hack/govulncheck.sh (1)

33-35: ⚠️ Potential issue | 🔴 Critical

The jq filter is incompatible with govulncheck -json v1.1.4 output format and will silently fail to detect vulnerabilities.

The govulncheck v1.1.4 JSON output is a stream of Message objects where each message contains exactly one top-level field: config, progress, SBOM, osv, or finding. The current filter assumes a .vulnerability.modules[]? structure that does not exist in this version, causing modvulns and libvulns to always be empty. This silently defeats the vulnerability detection, allowing the script to exit 0 even when vulnerabilities are present.

The filter must be rewritten to iterate over streaming JSON messages and extract vulnerability data from the finding messages (which contain osv, fixed_version, and vulnerability trace information), not from a non-existent .vulnerability object.

🧹 Nitpick comments (2)
Makefile (1)

390-392: make vex runs the full vulnerability-check pipeline, not just VEX generation.

The vex target invokes the same hack/govulncheck.sh script as verify-govulncheck. This means make vex will also install system packages via apt-get, run a second govulncheck -json pass, and exit 1 if module vulnerabilities are found. A user running make vex to generate a local report (as documented in SECURITY.md) may not expect this behavior.

Consider splitting the script or gating the verify portion behind an environment variable so make vex only produces build/cri-o.openvex.json.

scripts/release-notes/release_notes.go (1)

199-228: The Fprintf with 50+ positional %s args is fragile and hard to audit.

Every time a new artifact is added (as in this PR), someone must carefully count positions to insert new bundleVersion args at the right spot. A mismatch silently corrupts the rendered release notes.

Consider switching to text/template or strings.NewReplacer with named placeholders (e.g., {{.BundleVersion}}) to make the template self-documenting and less error-prone.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In @.github/workflows/test.yml:
- Around line 324-340: The vex-upload job currently requires security-checks to
succeed and will be skipped on failure; update the job-level if expression for
the job named vex-upload so it still runs for the target refs even when
security-checks failed but not when it was cancelled — e.g. replace the existing
if with a combined condition that preserves the ref checks and adds
needs.security-checks.result != 'cancelled' (refer to the job name vex-upload
and the needs: security-checks reference).

In `@hack/govulncheck.sh`:
- Around line 25-36: Update the second govulncheck invocation to use the modern
flag (replace the legacy "-json" with "-format json" on the govulncheck call
assigned to report) so both invocations use consistent flags, and then
consolidate the duplicate scans by running govulncheck a single time and
producing both outputs from that single run (e.g., run govulncheck once into a
temp file and write both build/cri-o.openvex.json and the JSON report from that
single result), changing the two separate "$GOPATH_BIN"/govulncheck calls to a
single invocation and using post-processing/tee to emit both formats.
🧹 Nitpick comments (1)
.github/workflows/test.yml (1)

315-320: Consider using if: !cancelled() instead of if: always().

if: always() will also execute when the workflow is cancelled. A more precise condition is if: !cancelled(), which runs on both success and failure but respects cancellation.

Proposed change
       - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
-        if: always()
+        if: '!cancelled()'
         with:
           name: vex
           path: build/cri-o.openvex.json
           if-no-files-found: ignore

Comment thread .github/workflows/test.yml
Comment thread hack/govulncheck.sh Outdated
@codecov

codecov Bot commented Feb 16, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 67.46%. Comparing base (57a6eba) to head (c355bea).
⚠️ Report is 4 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #9767      +/-   ##
==========================================
+ Coverage   67.32%   67.46%   +0.13%     
==========================================
  Files         210      210              
  Lines       29112    29112              
==========================================
+ Hits        19600    19639      +39     
+ Misses       7820     7778      -42     
- Partials     1692     1695       +3     
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Signed-off-by: Sascha Grunert <sgrunert@redhat.com>
@saschagrunert

Copy link
Copy Markdown
Member Author

/retest

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
scripts/release-notes/release_notes.go (1)

199-228: The positional %s approach with 55 arguments is extremely fragile — consider switching to named template parameters.

The new lines add 4 more bundleVersion arguments (lines 226-227) to an already massive Sprintf call. A single miscounted %s silently shifts every subsequent value, and this is practically impossible to audit by eye. I verified the counts appear correct for this change, but this is one-off luck at this scale.

Consider refactoring to strings.NewReplacer or text/template with a data struct, which would make the template self-documenting and immune to positional drift. This is pre-existing tech debt, so not blocking.

@saschagrunert saschagrunert changed the title WIP: Add OpenVEX report generation via govulncheck Add OpenVEX report generation via govulncheck Feb 16, 2026
@openshift-ci openshift-ci Bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Feb 16, 2026
@saschagrunert

Copy link
Copy Markdown
Member Author

@cri-o/cri-o-maintainers PTAL

with:
name: vex
path: build/cri-o.openvex.json
if-no-files-found: ignore

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.

in which case we fail to generate the file?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

It's just a safeguard if govulncheck tool fails to run.

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.

Shouldn't we fail the pipeline then?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

We already do. If govulncheck fails to run, the make verify-govulncheck step fails the job. The if-no-files-found: ignore only prevents a redundant error from the upload step.

Case 1: govulncheck runs, no vulns found

  security-checks job                             vex-upload job
  (all branches)                                  (main/release/tags only)

  +---------------------+    +----------------+   +------------------+   +-----------+
  | make govulncheck    |    | upload-artifact|   | download-artifact|   | upload    |
  |                     |    |                |   |                  |   | to GCS    |
  | VEX file:  created  |--->| VEX file:      |-->| VEX file:        |-->|           |
  | Vuln check: pass    |    | uploaded       |   | downloaded       |   | PASS      |
  +---------------------+    +----------------+   +------------------+   +-----------+
  Result: PASS                                     Result: PASS


Case 2: govulncheck runs, vulns found

  security-checks job                             vex-upload job
  (all branches)                                  (main/release/tags only, if: !cancelled())

  +---------------------+    +----------------+   +------------------+   +-----------+
  | make govulncheck    |    | upload-artifact|   | download-artifact|   | upload    |
  |                     |    | (if: always)   |   |                  |   | to GCS    |
  | VEX file:  created  |--->| VEX file:      |-->| VEX file:        |-->|           |
  | Vuln check: FAIL    |    | uploaded       |   | downloaded       |   | PASS      |
  +---------------------+    +----------------+   +------------------+   +-----------+
  Result: FAIL                                     Result: PASS (VEX still uploaded)


Case 3: govulncheck fails to install/run

  security-checks job                             vex-upload job
  (all branches)                                  (main/release/tags only, if: !cancelled())

  +---------------------+    +----------------+   +------------------+
  | make govulncheck    |    | upload-artifact|   | download-artifact|
  |                     |    | (if: always)   |   |                  |
  | VEX file:  none     |--->| VEX file:      |-->| no artifact      |
  | Script:    FAIL     |    | ignored        |   | FAIL             |
  +---------------------+    +----------------+   +------------------+
  Result: FAIL               ^                     Result: FAIL
                             |
                     if-no-files-found: ignore
                     prevents a redundant error here

In all failure cases the pipeline already fails. The ignore only matters in case 3 to avoid a noisy second error on the upload-artifact step. The vex-upload job uses !cancelled() so it still runs when vulns are found (case 2), ensuring the VEX report is uploaded to GCS even on failure.

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.

make sense thanks!

@bitoku

bitoku commented Feb 18, 2026

Copy link
Copy Markdown
Contributor

/lgtm

@openshift-ci openshift-ci Bot added the lgtm Indicates that a PR is ready to be merged. label Feb 18, 2026
@saschagrunert

Copy link
Copy Markdown
Member Author

/override ci/prow/e2e-gcp-ovn
/override ci/prow/e2e-aws-ovn

Unrelated.

@openshift-ci

openshift-ci Bot commented Feb 18, 2026

Copy link
Copy Markdown
Contributor

@saschagrunert: Overrode contexts on behalf of saschagrunert: ci/prow/e2e-aws-ovn, ci/prow/e2e-gcp-ovn

Details

In response to this:

/override ci/prow/e2e-gcp-ovn
/override ci/prow/e2e-aws-ovn

Unrelated.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@openshift-merge-bot openshift-merge-bot Bot merged commit 221a14d into cri-o:main Feb 18, 2026
83 of 84 checks passed
@saschagrunert saschagrunert deleted the vex-support branch February 18, 2026 14:28
@openshift-ci

openshift-ci Bot commented Feb 18, 2026

Copy link
Copy Markdown
Contributor

@saschagrunert: The following tests failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/e2e-aws-ovn c355bea link unknown /test e2e-aws-ovn
ci/prow/e2e-gcp-ovn c355bea link unknown /test e2e-gcp-ovn

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

@codecov

codecov Bot commented Feb 18, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 67.46%. Comparing base (57a6eba) to head (c355bea).
⚠️ Report is 4 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #9767      +/-   ##
==========================================
+ Coverage   67.32%   67.46%   +0.13%     
==========================================
  Files         210      210              
  Lines       29112    29112              
==========================================
+ Hits        19600    19639      +39     
+ Misses       7820     7778      -42     
- Partials     1692     1695       +3     
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. dco-signoff: yes Indicates the PR's author has DCO signed all their commits. kind/feature Categorizes issue or PR as related to a new feature. lgtm Indicates that a PR is ready to be merged. release-note Denotes a PR that will be considered when it comes time to generate release notes.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Vulnerability Exploitability eXchange (VEX)

2 participants