CycloneDX / CycloneDX/cyclonedx-gomod
cyclonedx-gomod creates circular dependency when package depends on older version of itself
- Dominant language
- Go
- Stars
- 187
- Forks
- 40
- Avg merge
- 1d 7h
- Merged PRs (30d)
- 14
Description
## Description
When a Go module depends on two different versions of the same package (e.g., a newer version depends on an older version), `cyclonedx-gomod` incorrectly merges them into a single component and creates a circular dependency reference instead of creating separate component entries for each version.
## Environment
- **cyclonedx-gomod version**: v1.9.0
- **Go version**: 1.25.0
- **OS**: macOS (also likely affects other platforms)
- **Command used**:
```bash
cyclonedx-gomod mod -licenses -test -output sbom.yml -output-version "1.4" -verbose=true
cyclonedx-gomod mod -licenses -test -output sbom.yml -output-version "1.5" -verbose=true
cyclonedx-gomod mod -licenses -test -output sbom.yml -output-version "1.6" -verbose=true
```
## Steps to Reproduce
1. Use a Go project that depends on `github.com/tedsuo/ifrit@v0.0.0-20230516164442-7862c310ad26`
2. Note that this version itself depends on `github.com/tedsuo/ifrit@v0.0.0-20230330192023-5cba443a66c4` (older version)
3. Verify with `go mod graph`:
```bash
go mod graph | grep -E "tedsuo/ifrit.*tedsuo/ifrit"
```
Output:
```
github.com/tedsuo/ifrit@v0.0.0-20230516164442-7862c310ad26 github.com/tedsuo/ifrit@v0.0.0-20230330192023-5cba443a66c4
```
4. Run cyclonedx-gomod with various output versions (1.4, 1.5, 1.6) - all produce the same issue
5. Examine the generated SBOM
## Expected Behavior
The SBOM should contain:
1. **Two separate component entries**:
- Component for `pkg:golang/github.com/tedsuo/ifrit@v0.0.0-20230516164442-7862c310ad26`
- Component for `pkg:golang/github.com/tedsuo/ifrit@v0.0.0-20230330192023-5cba443a66c4`
2. **Correct dependency relationship**:
```xml
```
## Actual Behavior
The SBOM only contains:
1. **One component entry** (only the newer version):
- Component for `pkg:golang/github.com/tedsuo/ifrit@v0.0.0-20230516164442-7862c310ad26`
- Missing component for the older version
2. **Circular dependency** (self-reference):
```xml
```
## Root Cause
The tool appears to be deduplicating packages by name only, without considering version differences. When building the dependency graph, it then creates a reference to the deduplicated component, resulting in a self-reference rather than a reference to the distinct older version.
## Impact
1. **SBOM validation failures**: SBOMs with circular dependencies may fail validation in some tools
2. **Inaccurate dependency graphs**: Downstream tools cannot accurately analyze the true dependency tree
3. **Security scanning issues**: Vulnerability scanners may miss issues in the older version since it's not represented as a separate component
## Additional Context
This is valid Go module behavior - a package can legitimately depend on an older version of itself. Go's module system handles this correctly via [Minimal Version Selection (MVS)](https://go.dev/ref/mod#minimal-version-selection), and `go mod graph` correctly shows both versions as distinct nodes in the dependency graph.
The SBOM generator should preserve this version-specific dependency information rather than collapsing it into a single component.
## Workaround
Currently, the only workaround is to manually edit the generated SBOM to:
1. Add the missing component entry for the older version
2. Update the dependency reference to point to the correct version
However, this must be redone every time the SBOM is regenerated.
## Related Issues
I do not know of any related issues at this time, but this may be a common scenario for Go projects that use older versions of dependencies.
Contributor guide
Research direction
Reproduce the issue with the listed cyclonedx-gomod command and the github.com/tedsuo/ifrit dependency graph from go mod graph. Trace the component deduplication and dependency-reference generation, then verify that both versions appear as separate components and that the newer version points to the older one without a circular reference.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- devtools
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100