Skip to content

Commit

Permalink
feat: handle orphan indirect depenencies
Browse files Browse the repository at this point in the history
Signed-off-by: knqyf263 <[email protected]>
  • Loading branch information
knqyf263 committed Nov 22, 2024
1 parent 29d73fb commit 539b6ab
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 0 deletions.
37 changes: 37 additions & 0 deletions pkg/fanal/analyzer/language/golang/mod/mod.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ func (a *gomodAnalyzer) PostAnalyze(_ context.Context, input analyzer.PostAnalys
a.logger.Warn("Unable to collect additional info", log.Err(err))
}

// Add orphan indirect dependencies under the main module
a.addOrphanIndirectDepsUnderRoot(apps)

return &analyzer.AnalysisResult{
Applications: apps,
}, nil
Expand Down Expand Up @@ -212,6 +215,40 @@ func (a *gomodAnalyzer) collectDeps(modDir, pkgID string) (types.Dependency, err
}, nil
}

// addOrphanIndirectDepsUnderRoot handles indirect dependencies that have no identifiable parent packages in the dependency tree.
// This situation can occur when:
// - $GOPATH/pkg directory doesn't exist
// - Module cache is incomplete
// - etc.
//
// In such cases, indirect packages become "orphaned" - they exist in the dependency list
// but have no connection to the dependency tree. This function resolves this issue by:
// 1. Finding the root (main) module
// 2. Identifying all indirect dependencies that have no parent packages
// 3. Adding these orphaned indirect dependencies under the main module
//
// This ensures that all packages remain visible in the dependency tree, even when the complete
// dependency chain cannot be determined.
func (a *gomodAnalyzer) addOrphanIndirectDepsUnderRoot(apps []types.Application) {
for _, app := range apps {
// Find the main module
_, rootIdx, found := lo.FindIndexOf(app.Packages, func(pkg types.Package) bool {
return pkg.Relationship == types.RelationshipRoot
})
if !found {
continue
}

// Collect all orphan indirect dependencies that are unable to identify parents
parents := app.Packages.ParentDeps()
orphanDeps := lo.FilterMap(app.Packages, func(pkg types.Package, _ int) (string, bool) {
return pkg.ID, pkg.Relationship == types.RelationshipIndirect && len(parents[pkg.ID]) == 0
})
// Add orphan indirect dependencies under the main module
app.Packages[rootIdx].DependsOn = append(app.Packages[rootIdx].DependsOn, orphanDeps...)
}
}

func parse(fsys fs.FS, path string, parser language.Parser) (*types.Application, error) {
f, err := fsys.Open(path)
if err != nil {
Expand Down
63 changes: 63 additions & 0 deletions pkg/fanal/analyzer/language/golang/mod/mod_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,69 @@ func Test_gomodAnalyzer_Analyze(t *testing.T) {
},
},
},
{
name: "no pkg dir found",
files: []string{
"testdata/no-pkg-found/mod",
},
want: &analyzer.AnalysisResult{
Applications: []types.Application{
{
Type: types.GoModule,
FilePath: "go.mod",
Packages: types.Packages{
{
ID: "github.com/org/repo",
Name: "github.com/org/repo",
Relationship: types.RelationshipRoot,
DependsOn: []string{
"github.com/aquasecurity/[email protected]",
"github.com/aquasecurity/[email protected]",
"golang.org/x/[email protected]", // No parent found, so it's added here.
},
ExternalReferences: []types.ExternalRef{
{
Type: types.RefVCS,
URL: "https://github.com/org/repo",
},
},
},
{
ID: "github.com/aquasecurity/[email protected]",
Name: "github.com/aquasecurity/go-dep-parser",
Version: "v1.0.0",
Relationship: types.RelationshipDirect,
ExternalReferences: []types.ExternalRef{
{
Type: types.RefVCS,
URL: "https://github.com/aquasecurity/go-dep-parser",
},
},
},
{
ID: "github.com/aquasecurity/[email protected]",
Name: "github.com/aquasecurity/go-version",
Version: "v1.0.1",
Relationship: types.RelationshipDirect,
ExternalReferences: []types.ExternalRef{
{
Type: types.RefVCS,
URL: "https://github.com/aquasecurity/go-version",
},
},
},
{
ID: "golang.org/x/[email protected]",
Name: "golang.org/x/xerrors",
Version: "v0.0.0-20200804184101-5ec99f83aff1",
Relationship: types.RelationshipIndirect,
Indirect: true,
},
},
},
},
},
},
{
name: "less than 1.17",
files: []string{
Expand Down

0 comments on commit 539b6ab

Please sign in to comment.