Skip to content

fix(cvss): honor Exploit Maturity threat metric in CVSS v4.0 scoring [Backport release/0.6.z] - #2575

Merged
mrrajan merged 4 commits into
release/0.6.zfrom
backport-2569-to-release/0.6.z
Aug 13, 2026
Merged

fix(cvss): honor Exploit Maturity threat metric in CVSS v4.0 scoring [Backport release/0.6.z]#2575
mrrajan merged 4 commits into
release/0.6.zfrom
backport-2569-to-release/0.6.z

Conversation

@trustify-ci-bot

@trustify-ci-bot trustify-ci-bot Bot commented Aug 12, 2026

Copy link
Copy Markdown

Description

Backport of #2569 to release/0.6.z.

Summary by Sourcery

Adjust CVSS v4.0 scoring to honor the Exploit Maturity metric and persist total component counts in exploit-intelligence jobs for more accurate status reporting.

New Features:

  • Support CVSS v4.0 full score calculation, including Exploit Maturity, when deriving vulnerability score information.

Enhancements:

  • Record total component counts on exploit-intelligence jobs when analyses complete or fail to provide consistent summary metrics.
  • Tighten exploit-intelligence job detail assertions to validate product identifiers, report URLs, and per-component counters across SBOM and product flows.
  • Simplify exploit-intelligence service APIs by removing the dedicated job-creation helper for multi-component products.

Tests:

  • Add CVSS v4.0 tests covering different Exploit Maturity values to verify correct scoring and severity classification.
  • Extend exploit-intelligence service, runner, and endpoint tests to assert total_components, product_id, and component-level counters for various job outcomes.

Strum355 and others added 3 commits August 12, 2026 14:02
Use calculated_full_score() instead of calculated_base_score() for v4.0
so E:P/E:U are not stripped. No change for CVEs without an E metric.

Implements TC-5626

Assisted-by: Claude Code
(cherry picked from commit ca49359)
Add missing test for CVSS v4.0 with E:A (Attacked) exploit maturity metric
as requested in PR review. Also fix variable name inconsistency where the
local variable was renamed to full_score but still referenced cvss.full_score
instead of cvss.base_score in the fallback.

Addresses review feedback on PR #2569

Co-Authored-By: Claude Code <noreply@anthropic.com>
(cherry picked from commit a837282)
@sourcery-ai

sourcery-ai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Backport that fixes CVSS v4.0 scoring to honor Exploit Maturity (E) and enriches exploit-intelligence job/component accounting by correctly setting total_components and tightening assertions in tests and runner/service logic.

Sequence diagram for updated CVSS v4.0 scoring using Exploit Maturity (sequence)

sequenceDiagram
    participant CvssV4 as CvssV4
    participant ScoreInformation as ScoreInformation

    CvssV4->>CvssV4: calculated_full_score()
    alt full_score is Some
        CvssV4-->>ScoreInformation: full_score
    else full_score is None
        CvssV4->>CvssV4: CvssV4::from_str(vector_string)
        CvssV4->>CvssV4: calculated_full_score()
        CvssV4-->>ScoreInformation: full_score_or_none
        ScoreInformation->>ScoreInformation: unwrap_or(cvss.base_score)
    end

    ScoreInformation->>ScoreInformation: score = full_score as f32
    ScoreInformation->>ScoreInformation: severity = (full_score, ScoreType::V4_0).into()
Loading

Sequence diagram for exploit-intelligence job completion/failure with total_components (sequence)

sequenceDiagram
    participant Runner as poll_for_product_result
    participant EiService as ExploitIntelligenceService
    participant DB as Database

    Runner->>EiService: fetch_components(job_id, DB)
    EiService-->>Runner: components
    Runner->>Runner: [compute total = Some(components.len() as i32)]
    alt has_finding or all_excluded
        Runner->>EiService: update_job_completed(job_id, total, DB)
        EiService->>DB: update exploit_intelligence_job (status=Completed, total_components)
        DB-->>EiService: ok
        EiService-->>Runner: ok
    else no_findings and not_all_excluded
        Runner->>EiService: update_job_failed(job_id, error_message, total, DB)
        EiService->>DB: update exploit_intelligence_job (status=Failed, total_components)
        DB-->>EiService: ok
        EiService-->>Runner: ok
    end
Loading

File-Level Changes

Change Details Files
Use CVSS v4.0 full score (including Exploit Maturity E metric) instead of base score, with tests covering different E values.
  • Change ScoreInformation::from<(String, v4_0::CvssV4)> to use calculated_full_score with fallback parsing, instead of calculated_base_score.
  • Propagate the full_score into both score and severity fields in ScoreInformation.
  • Add unit tests verifying scores for vectors with E:P, E:A, E:U, and without E to ensure Exploit Maturity affects v4.0 scoring correctly.
modules/ingestor/src/graph/cvss.rs
Track and persist total_components on exploit-intelligence jobs and align service, runner, worker, and endpoint tests with this richer job detail model.
  • Extend ExploitIntelligenceService::update_job_completed and ::update_job_failed to accept optional total_components and set the ActiveModel field using NotSet when absent.
  • Remove the obsolete create_job_with_product helper now that total_components is managed via update paths.
  • Update runners (polling, worker) to compute total component counts from fetched components where appropriate and pass them into update_job_completed/update_job_failed (including product analysis flows and retry exhaustion cases).
  • Adjust endpoints tests and service tests to create jobs with appropriate total_components values and assert expected job detail fields (finding, product_id, report_url, total/failed/completed/excluded/vulnerable/not_vulnerable/uncertain component counts, and component list status/properties).
  • Update runner tests to reflect the new update_job_failed signature (adding total_components parameter) and to validate detailed job/component accounting in various success/failure scenarios.
modules/exploit-intelligence/src/service/mod.rs
modules/exploit-intelligence/src/service/test.rs
modules/exploit-intelligence/src/runner/polling.rs
modules/exploit-intelligence/src/runner/worker.rs
modules/exploit-intelligence/src/runner/test.rs
modules/exploit-intelligence/src/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 left some high level feedback:

  • In poll_for_result the total_components is hard-coded to Some(1) when marking jobs completed; if this pipeline can ever handle more than one component, consider deriving the count from fetch_components as you do in poll_for_product_result to keep summary metrics consistent.
  • The new total_components: Option<i32> parameter on update_job_failed is only populated in some flows; review the various failure cases (e.g., product-level failures, timeout) to see if you can pass a meaningful component count where it is already known so that job summaries stay aligned across success and failure paths.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `poll_for_result` the `total_components` is hard-coded to `Some(1)` when marking jobs completed; if this pipeline can ever handle more than one component, consider deriving the count from `fetch_components` as you do in `poll_for_product_result` to keep summary metrics consistent.
- The new `total_components: Option<i32>` parameter on `update_job_failed` is only populated in some flows; review the various failure cases (e.g., product-level failures, timeout) to see if you can pass a meaningful component count where it is already known so that job summaries stay aligned across success and failure paths.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Resolved conflict in modules/exploit-intelligence/src/endpoints/test.rs
by combining both changes:
- Kept the updated field RFC3339 assertion from release/0.6.z
- Kept the total_components assertion with JSON indexing syntax
- Fixed comment for updated field assertion

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@mrrajan
mrrajan merged commit 422e346 into release/0.6.z Aug 13, 2026
8 checks passed
@mrrajan
mrrajan deleted the backport-2569-to-release/0.6.z branch August 13, 2026 07:58
@github-project-automation github-project-automation Bot moved this to Done in Trustify Aug 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants