Skip to content

Conversation

@DmitriyLewen
Copy link
Contributor

Description

This PR fixes a critical bug in VEX (Vulnerability Exploitability eXchange) processing where the visited set was being shared across different dependency paths during depth-first search traversal. The issue caused incorrect
vulnerability filtering when multiple parents had dependencies on the same component.

Reasons

The original implementation had a fundamental flaw where the visited map was shared across all recursive paths in the DFS traversal. This meant that if component A was visited through one parent path, it would be marked as visited for
all other parent paths, potentially causing the algorithm to incorrectly conclude that a component couldn't reach the root when it actually could through a different path.

This bug was particularly problematic in scenarios with diamond dependencies (multiple paths to the same component) and could lead to incorrect vulnerability filtering decisions in VEX processing.

Related issues

Related PRs

Checklist

  • I've read the guidelines for contributing to this repository.
  • I've followed the conventions in the PR title.
  • I've added tests that prove my fix is effective or that my feature works.
  • I've updated the documentation with the relevant information (if needed).
  • I've added usage information (if the PR introduces new options)
  • I've included a "before" and "after" example to the description (if the PR is a user interface change).

@DmitriyLewen DmitriyLewen changed the title test(vex): add test fix(vex): use a separate visited set for each tree path. Nov 6, 2025
@DmitriyLewen DmitriyLewen changed the title fix(vex): use a separate visited set for each tree path. fix(vex): use a separate visited set for each DFS path Nov 6, 2025
@DmitriyLewen DmitriyLewen self-assigned this Nov 6, 2025
@DmitriyLewen
Copy link
Contributor Author

As an alternative solution, we can merge #9007 and revert #9465.
#9007 will solve the problem with cyclic dependencies (since all of them will be linked to the root component),
and reverting of 9465 will remove the incorrect parent check (the visited function).

@DmitriyLewen DmitriyLewen marked this pull request as ready for review November 7, 2025 08:53
Comment on lines +603 to +609
name: "check one parent from multiple dependency paths",
args: args{
// - oci:debian?tag=12
// - pkg:deb/debian/[email protected]
// - pkg:deb/debian/[email protected]
// - pkg:deb/debian/[email protected]
// - pkg:deb/debian/[email protected]
Copy link
Collaborator

Choose a reason for hiding this comment

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

This test case looks like multiple parents ([email protected] and [email protected]) from a single dependency ([email protected]). Am I missing something?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Right.
But oci:debian?tag=12 is the parent for both [email protected] and [email protected].

For this test case there are two dependency paths:

  1. pkg:deb/debian/[email protected] -> pkg:deb/debian/[email protected] -> oci:debian?tag=12
  2. pkg:deb/debian/[email protected] -> pkg:deb/debian/[email protected] -> oci:debian?tag=12

After the first path, we mark oci:debian?tag=12 as visited.
When we process pkg:deb/debian/[email protected], we see that oci:debian?tag=12 is already visited and return true.

@knqyf263
Copy link
Collaborator

#9007 will solve the problem with cyclic dependencies (since all of them will be linked to the root component),

I reviewed the change and I’m leaning toward this idea. However, it's not good to often change the SBOM structure. What do you think?

@DmitriyLewen
Copy link
Contributor Author

I also don’t like changing the logic back and forth (since #9007 is basically a revert of the changes as well).
That’s actually why I created this PR.

However, we still need to fix #9011 somehow.

We can consider the first fix option (9f4702c).
I mean the logic where we add relationships only for orphan packages.
But then we have a choice:

  • simpler logic, but effectively a revert
  • more complex logic

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.

bug(vex): Trivy skips the rule if we check the same parent from different paths.

2 participants