Incomplete Dependency Graph Generation in dependency-scanning Analyzer for Go Projects

Description

The dependency-scanning analyzer is currently generating inaccurate dependency graphs from go.mod and go.graph files. Two specific issues have been identified:

  1. Incorrect Dependency Relationships

    • All modules are being represented as direct dependencies in the CycloneDX output
    • This contradicts the actual dependency structure defined in go.mod, which clearly distinguishes between direct and indirect dependencies through comment annotations
  2. Missing Dependency Paths

    • The CycloneDX graph paths are incomplete
    • Example: Running go mod why gopkg.in/yaml.v2 reveals a path through the rulesets module that is not reflected in the generated graph

Proposed Solution

The dependency graph generation logic needs to be revised to:

  • Properly parse and respect the direct/indirect dependency relationships from go.mod
  • Include all valid dependency paths in the graph structure

Impact

This issue affects the accuracy of dependency scanning results and could lead to incorrect vulnerability assessments or dependency tracking.

Steps to Reproduce

  1. Check the artifacts of a dependency scanning job: Example Job Artifacts
  2. Compare the generated CycloneDX output with the actual go.mod file structure
  3. Run go mod why for specific dependencies to verify missing paths

Cause

There seem two broad classes of error causing the bug.

  1. The parsing uses go.graph for direct node checks but this seems to be flaky for most cases.
  2. Go graph parsing filters modules it finds against the list discovered during go.mod parsing. As a result, an edge may be missing because a transitive dependency did not appear in the original parsing. Or, if a module version differs from the one recorded that edge will be skipped rather than resolving the module to the correct version via MVS.

Proposal

Update parser implementation to use modfile.Require which reliably indicates which modules are direct. Currently a flaky implementation, of trying to find the application edge, is used. Include edges pointing to modules not in go.mod or versions different from those originally recorded.

Implementation plan

  • Use modfile.Require for identifying direct dependencies rather than finding application edges in go.graph.
  • Fix removal of modules found in go.graph if they are not found in go.mod.
  • Fix skipping of modules that do not match originally recorded versions.
Edited by Igor Frenkel