-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(sbom): improve logic for binding direct dependency to parent component #8489
Merged
DmitriyLewen
merged 3 commits into
aquasecurity:main
from
DmitriyLewen:fix-sbom/handle-direct-indirect-dep
Mar 5, 2025
Merged
fix(sbom): improve logic for binding direct dependency to parent component #8489
DmitriyLewen
merged 3 commits into
aquasecurity:main
from
DmitriyLewen:fix-sbom/handle-direct-indirect-dep
Mar 5, 2025
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
knqyf263
reviewed
Mar 5, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it work?
diff --git a/pkg/sbom/io/encode.go b/pkg/sbom/io/encode.go
index cf2c54648..8c9ea69a8 100644
--- a/pkg/sbom/io/encode.go
+++ b/pkg/sbom/io/encode.go
@@ -200,6 +200,7 @@ func (e *Encoder) encodePackages(parent *core.Component, result types.Result) {
components := make(map[string]*core.Component, len(result.Packages))
// PkgID => Package Component
dependencies := make(map[string]*core.Component, len(result.Packages))
+ var hasRoot bool
for i, pkg := range result.Packages {
pkgID := lo.Ternary(pkg.ID == "", fmt.Sprintf("%s@%s", pkg.Name, pkg.Version), pkg.ID)
result.Packages[i].ID = pkgID
@@ -219,6 +220,12 @@ func (e *Encoder) encodePackages(parent *core.Component, result types.Result) {
if vv := vulns[pkg.Identifier.UID]; vv != nil {
e.bom.AddVulnerabilities(c, vv)
}
+
+ // Check if the project has a root dependency
+ // TODO: Ideally, all projects should have a root dependency.
+ if pkg.Relationship == ftypes.RelationshipRoot {
+ hasRoot = true
+ }
}
// Build a dependency graph between packages
@@ -226,7 +233,7 @@ func (e *Encoder) encodePackages(parent *core.Component, result types.Result) {
c := components[pkg.Identifier.UID]
// Add a relationship between the parent and the package if needed
- if e.belongToParent(pkg, parents) {
+ if e.belongToParent(pkg, parents, hasRoot) {
e.bom.AddRelationship(parent, c, core.RelationshipContains)
}
@@ -403,16 +410,15 @@ func (*Encoder) vulnerability(vuln types.DetectedVulnerability) core.Vulnerabili
}
// belongToParent determines if a package should be directly included in the parent based on its relationship and dependencies.
-func (*Encoder) belongToParent(pkg ftypes.Package, parents map[string]ftypes.Packages) bool {
+func (*Encoder) belongToParent(pkg ftypes.Package, parents map[string]ftypes.Packages, hasRoot bool) bool {
// Case 1: Relationship: known , DependsOn: known
// Packages with no parent are included in the parent
// - Relationship:
// - Root: true (it doesn't have a parent)
// - Workspace: false (it always has a parent)
// - Direct:
- // - Under Root or Workspace: false (it always has a parent)
- // - No parents: true (e.g., package-lock.json)
- // - There are parents, but they are not Root or Workspace: true (when indirect dependency was installed manually. cf. https://github.com/aquasecurity/trivy/issues/8488)
+ // - No root dependency in the project: true (e.g., poetry.lock)
+ // - Otherwise: false (Direct dependencies should belong to the root/workspace)
// - Indirect: false (it always has a parent)
// Case 2: Relationship: unknown, DependsOn: unknown (e.g., conan lockfile v2)
// All packages are included in the parent
@@ -421,16 +427,10 @@ func (*Encoder) belongToParent(pkg ftypes.Package, parents map[string]ftypes.Pac
// Case 4: Relationship: unknown, DependsOn: known (e.g., GoBinaries, OS packages)
// - Packages with parents: false. These packages are included in the packages from `parents` (e.g. GoBinaries deps and root package).
// - Packages without parents: true. These packages are included in the parent (e.g. OS packages without parents).
- pkgParents := parents[pkg.ID]
- if pkg.Relationship != ftypes.RelationshipDirect {
- return len(pkgParents) == 0
+ if pkg.Relationship == ftypes.RelationshipDirect {
+ return !hasRoot
}
-
- _, found := lo.Find(pkgParents, func(pkg ftypes.Package) bool {
- return pkg.Relationship == ftypes.RelationshipRoot || pkg.Relationship == ftypes.RelationshipWorkspace
- })
-
- return !found
+ return len(parents[pkg.ID]) == 0
}
func filterProperties(props []core.Property) []core.Property {
This seems better to me than my solution (we don't need to iterate over parents map for each package). Thanks! |
knqyf263
approved these changes
Mar 5, 2025
nikpivkin
reviewed
Mar 5, 2025
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Description
This PR improves
belongToParent
logic for Direct dependencies:Root
orWorkspace
- doesn't bind dependency to the parent component (current logic)Example:
before:
after:
Related issues
Related PRs
unknown
dependencies (if exists) #8104Checklist