Skip to content

fix(purl): filter recommend report vulns to fixed/not_affected only - #2727

Merged
ruromero merged 3 commits into
guacsec:mainfrom
ruromero:TC-6683
Oct 1, 2026
Merged

ruromero merged 3 commits into
guacsec:mainfrom
ruromero:TC-6683

Conversation

@ruromero

@ruromero ruromero commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Filter RecommendReportPackage.vulnerabilities[] to only include CVEs where the recommended PURL has fixed or not_affected VEX status
  • Exclude packages with zero addressed CVEs from the report entirely
  • Update impact_summary.addressable_packages and per-SBOM counts to reflect filtered results

Implements TC-6683

Test plan

  • Existing recommend report tests pass (8/8)
  • New test: mixed statuses — vendor backport fixes CVE-A but not CVE-B, only CVE-A appears
  • New test: package with zero fixed/not_affected CVEs excluded from report
  • cargo clippy and cargo fmt --check pass
  • cargo xtask precommit passes

🤖 Generated with Claude Code

Summary by Sourcery

Report only remediable vulnerabilities and omit packages that address none.

Bug Fixes:

  • Filter recommendation report vulnerabilities to CVEs addressed by the recommended package version through fixed or not_affected statuses.
  • Exclude packages with no addressed CVEs from recommendation reports and recalculate package and vulnerability counts accordingly.

Tests:

  • Add coverage for mixed vulnerability statuses and packages with no addressed CVEs.
@sourcery-ai

sourcery-ai Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Reviewer's Guide

The recommend report now presents only vulnerabilities resolved or explicitly not affecting the recommended PURL, omits packages with no such CVEs, and keeps package, SBOM, and impact-summary counts consistent with the filtered results. Tests add coverage for mixed statuses and fully unaddressed packages.

Flow diagram for filtering recommend report vulnerabilities

flowchart TD
    A[Build best advisory status per CVE] --> B{Status is fixed or not_affected?}
    B -->|Yes| C[Include CVE in vulnerabilities]
    B -->|No| D[Exclude CVE]
    C --> E{Any vulnerabilities remain?}
    E -->|Yes| F[Include package in report]
    E -->|No| G[Exclude package from report]
    F --> H[Update SBOM and impact summary counts]
    G --> H
Loading

File-Level Changes

Change Details Files
Filter recommended-package vulnerabilities to CVEs addressed by the recommended PURL and drop packages with no addressed vulnerabilities.
  • Retain only fixed and not_affected vulnerability statuses.
  • Skip package entries whose filtered vulnerability list is empty.
  • Continue deriving report package and advisory data from the remaining recommendation context.
modules/fundamental/src/purl/service/mod.rs
Expand recommend-report coverage for addressed, mixed-status, and entirely unaddressed vulnerability scenarios.
  • Update the existing status-filter test to expect not_affected CVEs and addressed counts.
  • Add a reusable minimal CSAF VEX fixture builder for component and status combinations.
  • Verify mixed fixed/affected results contain only the fixed CVE and update package/SBOM counts.
  • Verify packages with no fixed or not-affected CVEs are omitted and aggregate counts are zero.
modules/fundamental/src/purl/endpoints/test.rs

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai 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.

Hey - I've found 1 issue

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="modules/fundamental/src/purl/service/mod.rs" line_range="1168-1170" />
<code_context>
-                        "affected" | "under_investigation"
-                    )
-                })
+                .filter(|(_, info)| matches!(info.status_slug.as_str(), "fixed" | "not_affected"))
                 .map(|(id, _)| id.to_string())
                 .collect();

</code_context>
<issue_to_address>
**issue (broader_impact):** `advisory_id` is still selected from the most recent advisory across all vulnerabilities, including vulnerabilities filtered out because their status is `affected` or `under_investigation`. A package can therefore list only addressed CVEs while its provenance points to an advisory for an excluded CVE, misleading consumers about which advisory supports the recommendation.

**Triggers:** When an excluded vulnerability has a newer advisory than the fixed or not_affected vulnerabilities retained in the report.

**Suggested fix:** Select `advisory_id` from the retained addressed statuses, or otherwise ensure the selected advisory corresponds to at least one CVE in `vulnerabilities`.

```suggestion
            // Advisory ID from the most recent advisory among addressed vulnerabilities.
            let advisory_id = best_by_vuln
                .values()
                .filter(|info| matches!(info.status_slug.as_str(), "fixed" | "not_affected"))
                .max_by(|a, b| a.advisory_date.cmp(&b.advisory_date))
                .and_then(|info| info.advisory_id.clone());
```
</issue_to_address>

Sourcery assessment

Approval pending. 1 finding to address first.

Blocking findings: modules/fundamental/src/purl/service/mod.rs:1170


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Comment thread modules/fundamental/src/purl/service/mod.rs Outdated
@ruromero

Copy link
Copy Markdown
Contributor Author

Verification Report for TC-6683 (commit 859da6a)

Check Result Details
Review Feedback PASS 1 suggestion from sourcery-ai[bot] (advisory_id scope); classified as intentional design — no sub-task
Root-Cause Investigation N/A No sub-tasks created
Scope Containment PASS mod.rs (specified) + test.rs (justified by Test Requirements)
Diff Size PASS ~254 lines across 2 files; proportional to filter change + 2 new tests + helper
Commit Traceability PASS Commit 859da6a references "Implements TC-6683"
Sensitive Patterns PASS No secrets or credentials in any added line
CI Status WARN 5 passed, 3 pending (windows, bench, test), 0 failed
Acceptance Criteria PASS 5/5 criteria met
Test Quality PASS All tests documented, no repetitive patterns; Eval Quality: N/A
Test Change Classification ADDITIVE 1 test updated, 2 new tests added, 1 helper added
Verification Commands PASS cargo clippy and cargo fmt --check clean

Overall: WARN

CI checks still pending (windows, bench, test). No failures. All acceptance criteria met, all tests pass locally.


This comment was AI-generated by sdlc-workflow/verify-pr v0.13.9.

@ruromero
ruromero requested a review from a team September 30, 2026 20:38
The report's vulnerabilities[] was showing CVEs where the recommended
PURL was affected — misleading users into thinking those CVEs were
addressed. Now only CVEs where the recommended PURL has fixed or
not_affected VEX status are included. Packages with zero addressed
CVEs are excluded from the report entirely.

Implements TC-6683

Assisted-by: Claude Code
CSAF ingestion validates CVE IDs match ^CVE-[0-9]{4}-[0-9]{4,}$.
Test IDs like CVE-TEST-FIXED passed locally (lenient parsing) but
failed in CI. Use CVE-2024-9000x format instead.

Implements TC-6683

Assisted-by: Claude Code

@rh-jfuller rh-jfuller 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.

new filter limits vulnerabilities to fixed/not_affected but I think advisory_id is still selected from all best_by_vuln entries. If a newer advisory reports another CVE as affected, the package can list an older fixed CVE while naming the newer advisory as its provenance. Maybe select advisory from the statuses that contributed to the filtered list ?

otherwise LGTM

@ruromero

ruromero commented Oct 1, 2026

Copy link
Copy Markdown
Contributor Author

new filter limits vulnerabilities to fixed/not_affected but I think advisory_id is still selected from all best_by_vuln entries. If a newer advisory reports another CVE as affected, the package can list an older fixed CVE while naming the newer advisory as its provenance. Maybe select advisory from the statuses that contributed to the filtered list ?

Very good observation. I'll make the suggested change.

advisory_id was selected from all best_by_vuln entries, so a newer
advisory reporting a CVE as affected could become provenance for a
package whose displayed vulns come from an older fixed advisory.
Now advisory_id is filtered to fixed/not_affected statuses, matching
the vulnerabilities list.

Implements TC-6683

Assisted-by: Claude Code

@sourcery-ai sourcery-ai 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.

Sourcery assessment

Approved.

@rh-jfuller rh-jfuller 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.

LGTM

@ruromero
ruromero added this pull request to the merge queue Oct 1, 2026
@ruromero

ruromero commented Oct 1, 2026

Copy link
Copy Markdown
Contributor Author

[sdlc-workflow/verify-pr] Re: @rh-jfuller review — Classified as code change request — advisory_id scoping to addressed (fixed/not_affected) statuses. Already addressed in commit 6929ad1. No sub-task created.

@ruromero

ruromero commented Oct 1, 2026

Copy link
Copy Markdown
Contributor Author

Verification Report for TC-6683 (commit 6929ad1)

Check Result Details
Review Feedback PASS 1 code change request from rh-jfuller (advisory_id scope); addressed in commit 6929ad1. 1 prior suggestion from sourcery-ai (same topic). No sub-tasks.
Root-Cause Investigation N/A No sub-tasks created
Scope Containment PASS mod.rs (specified) + test.rs (justified by Test Requirements)
Diff Size PASS ~260 lines across 2 files; 3 commits proportional to filter change + advisory_id fix + tests
Commit Traceability PASS All 3 commits reference "Implements TC-6683"
Sensitive Patterns PASS No secrets in any added line
CI Status PASS All 10 checks pass (test, bench, ci, container, grype, macos, ubuntu, windows, supply-chain, sourcery)
Acceptance Criteria PASS 6/6 criteria met (including AC4: advisory_id scoped to addressed statuses)
Test Quality PASS All tests documented, no repetitive patterns; Eval Quality: N/A
Test Change Classification ADDITIVE 1 test updated, 2 new tests added, 1 helper added
Verification Commands PASS cargo clippy and cargo fmt --check clean

Overall: PASS

All checks pass. Reviewer feedback (advisory_id scoping) addressed. Two approvals (rh-jfuller, sourcery-ai). Ready to merge.


This comment was AI-generated by sdlc-workflow/verify-pr v0.13.9.

Merged via the queue into guacsec:main with commit e8ea4ed Oct 1, 2026
10 checks passed
@ruromero
ruromero deleted the TC-6683 branch October 1, 2026 10:48
@trustify-ci-bot

Copy link
Copy Markdown
@rh-jfuller

Copy link
Copy Markdown
Contributor

/perf-test

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

2 participants