Skip to content

[REVIEW] sbom-analysis: add graph completeness, VEX credibility, and freshness/trustworthiness gates #1535

@bnpl7

Description

@bnpl7

Skill Being Reviewed

Skill name: sbom-analysis
Skill path: skills/vuln-management/sbom-analysis/

False Positive Analysis

Benign SBOM that can be scored as "Complete" despite missing transitive dependency unfurl:

sbom_format: CycloneDX 1.5
total_components: 42 (direct: 12, transitive: 30)
ntia_minimum_elements:
  supplier_name: 100%
  component_name: 100%
  version: 100%
  unique_identifier: 100%
  dependency_relationship: 100%
  sbom_author: present
  timestamp: present
ntia_completeness_rating: Complete
observed_issue: |
  All 30 transitive components are listed with names and versions,
  but there is no dependency graph — the dependencies[] array
  only lists direct dependency relationships. Transitive components
  are "flat-listed" without parent-child linkage.

Why this is a false positive:
The skill's NTIA completeness check (Step 2) evaluates whether each of the seven minimum elements is present for each component. A flat list of transitive components with no dependency depth structure satisfies "Dependency Relationship" at the component level if each component has at least one relationship, but it does not provide the dependency graph needed for accurate transitive risk analysis. The NTIA minimum elements require "Dependency Relationship" but do not require a full graph — a flat list meets the letter but not the intent. The skill's completeness assessment does not distinguish "relationships listed for each component" from "full dependency graph available."

Benign VEX with credible "Not Affected" status that may still warrant precaution:

vex_entry:
  cve: CVE-2024-3094
  component: liblzma (xz-utils) 5.6.0
  status: Not Affected
  justification: vulnerable_code_not_in_execute_path
  vendor_statement: |
    The vulnerable library is bundled but not loaded at runtime
    in our application context. We have verified through code
    review that the backdoor code path is unreachable.
  verified_by_consumer: false (no independent code review performed)

Why this is a false positive:
The skill's VEX Interpretation section (Step 3) correctly documents that "Not Affected" with a justification should be trusted, and the "vulnerable_code_not_in_execute_path" justification is one of the five valid CSAF categories. However, the assessment output does not distinguish between vendor-attested "Not Affected" status and consumer-verified "Not Affected" status. In practice, a vendor VEX stating "vulnerable code not in execute path" may be based on different assumptions about how the component is integrated. The skill's output would record this as "Not Affected" without indicating whether the consumer independently verified the justification, which can lead to risk acceptance that is not evidence-backed.

Coverage Gaps

Missed variant 1: Transitive dependency unfurl completeness not in completeness assessment.

dependency_analysis:
  components_declared: 87
  dependency_relationships_filled: 87 (each component has at least one DEPENDS_ON)
  dependency_graph_depth: 1 (flat list — no relationship depth beyond direct)
  issue: |
    The SBOM has 87 components, but the dependency graph is flat.
    There is no way to determine which top-level component
    brings in which transitive dependency. A fix for a transitive
    CVE cannot be traced to the consuming component.

Why it should be caught:
The skill's NTIA completeness check rates "Dependency Relationship" based on the presence of at least one relationship per component, but it does not require that the dependency graph be complete enough to trace transitive depth. The transitive dependency analysis (Step 4) correctly identifies orphan components and dependency depth, but the overall completeness rating ("Complete", "Substantially Complete", etc.) does not incorporate graph completeness. A flat SBOM can receive "Complete" even though it cannot support transitive vulnerability triage. The skill should add a graph_completeness dimension to the NTIA assessment that requires traceable depth from top-level to all transitive components.

Missed variant 2: VEX justification credibility assessment not in output.

vex_entries:
  - cve: CVE-2024-3094
    component: xz-utils 5.6.0
    status: Not Affected
    justification: vulnerable_code_not_in_execute_path
    credibility: unknown (vendor statement only, no independent verification)
  - cve: CVE-2024-21626
    component: runc 1.1.11
    status: Not Affected
    justification: vulnerable_code_not_present
    credibility: verified (SBOM confirms component version does not contain affected code)

Why it should be caught:
The VEX Assessment section (Step 3) documents the VEX format, total entries, and counts by status, but does not include a credibility assessment for each VEX entry. A "Not Affected" with justification "vulnerable_code_not_in_execute_path" is verifiable only through code-level analysis, which is typically performed by the vendor, not the SBOM consumer. The skill should add a verification_status field per VEX entry: vendor_attested, consumer_verified, third_party_verified, or not_verified. Without this, the VEX summary can treat all "Not Affected" entries as equally credible, when some justifications require deeper consumer validation.

Missed variant 3: SBOM freshness and trustworthiness assessment absent from output.

sbom_metadata:
  timestamp: "2025-06-01T10:00:00Z"
  software_version: "4.2.0"
  latest_release_version: "5.1.0" (released 2026-03-15)
  sbom_age: 11 months
  last_cve_scan: "2025-06-01" (aligned with SBOM generation)
  build_provenance: unsigned (no SLSA provenance or attestation)

Why it should be caught:
The skill's common pitfalls include "Failing to track SBOM freshness," and the output format includes the SBOM timestamp. However, the format does not include a structured freshness and trustworthiness assessment. An 11-month-old SBOM for a software version that is multiple releases behind is not useful for current vulnerability management, but the current output would show "Complete" or "Substantially Complete" NTIA compliance without warning about staleness. The skill should add a freshness assessment (timestamp_vs_latest_release, cve_scan_currency, sbom_age_category) and a trustworthiness assessment (build provenance, signer identity, generation tool verification).

Edge Cases

  • CycloneDX 1.5 formulation data (build environment composition) is not assessed by the current skill, but it can contain dependency information that differs from the runtime SBOM.
  • SPDX 2.3 files and snippets sections can contain license and copyright data but are not analyzed by the NTIA completeness or license conflict detection.
  • VEX with "Under Investigation" status that has been in that state for months past the vendor's stated investigation timeline — the skill does not flag stale VEX entries.
  • Multi-SBOM compositions (a product composed of multiple sub-components each with their own SBOM) are not covered by the current NTIA and transitive analysis that assumes a single SBOM.

Remediation Quality

  • Fix resolves the vulnerability
  • Fix doesn't introduce new security issues
  • Fix doesn't break functionality
  • Issues found: Add graph completeness, VEX credibility, SBOM freshness/trustworthiness, and stale VEX detection to the output and completeness assessment.

Recommended additions:

  1. Add a graph_completeness metric to the NTIA assessment: traceable_depth_max, orphan_component_relationships, and a graph completeness rating (Complete Graph / Partial Graph / Flat List).
  2. Add a verification_status per VEX entry and a aggregate VEX credibility score.
  3. Add a structured freshness and trustworthiness section: SBOM age, version lag, CVE scan currency, build provenance level, and signer identity.
  4. Add stale VEX detection: flag VEX entries with "Under Investigation" status older than the vendor's stated investigation SLA.

Comparison to Other Tools

Tool Catches this? Notes
Dependency-Track Partial Tracks SBOM freshness and has VEX ingestion, but does not evaluate graph completeness or VEX credibility
Snyk Partial Evaluates transitive dependency risk but uses its own resolution graph, not the SBOM's declared relationships
Grype / Trivy No Vulnerability scanners that do not evaluate SBOM completeness, VEX credibility, or freshness
CISA SBOM Validation Tools No Validate schema and format but not graph completeness or VEX credibility

Overall Assessment

Strengths:

  • Comprehensive NTIA minimum elements completeness evaluation with per-element scoring.
  • Good VEX status interpretation with justification category reference.
  • Strong transitive dependency analysis with risk indicators (depth, fan-in, stale packages).
  • Clear license compatibility matrix with common conflict reference.

Needs improvement:

  • NTIA completeness rating does not incorporate dependency graph completeness — a flat list of transitive components can receive "Complete" without supporting traceable transitive analysis.
  • VEX assessment treats all "Not Affected" entries as equal without distinguishing vendor-attested from consumer-verified.
  • SBOM freshness and trustworthiness are mentioned in common pitfalls but not assessed in the structured output.
  • Stale VEX entries ("Under Investigation" beyond expected timeline) are not detected.

Priority recommendations:

  1. Add graph completeness to the NTIA completeness assessment — require traceable depth from top-level components to transitive leaves.
  2. Add VEX credibility fields (verification_status, verification_date, verifier) per entry and an aggregate credibility score.
  3. Add a structured freshness and trustworthiness section to the SBOM analysis report output format.
  4. Add stale VEX detection with SLA-based flagging for "Under Investigation" entries.

Sources Checked

Bounty Info

  • I have read and agree to the CONTRIBUTING.md bounty terms
  • Preferred payment method: PayPal, to be provided privately after acceptance

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions