Skip to content

Commit b836232

Browse files
feat(java): add empty versions if pom.xml dependency versions can't be detected (#7520)
Co-authored-by: Teppei Fukuda <knqyf263@gmail.com>
1 parent 60725f8 commit b836232

File tree

6 files changed

+108
-2
lines changed

6 files changed

+108
-2
lines changed

docs/docs/coverage/language/java.md

+11
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,16 @@ The vulnerability database will be downloaded anyway.
6969
!!! Warning
7070
Trivy may skip some dependencies (that were not found on your local machine) when the `--offline-scan` flag is passed.
7171

72+
### empty dependency version
73+
There are cases when Trivy cannot determine the version of dependencies:
74+
75+
- Unable to determine the version from the parent because the parent is not reachable;
76+
- The dependency uses a [hard requirement][version-requirement] with more than one version.
77+
78+
In these cases, Trivy uses an empty version for the dependency.
79+
80+
!!! Warning
81+
Trivy doesn't detect child dependencies for dependencies without a version.
7282

7383
### maven-invoker-plugin
7484
Typically, the integration tests directory (`**/[src|target]/it/*/pom.xml`) of [maven-invoker-plugin][maven-invoker-plugin] doesn't contain actual `pom.xml` files and should be skipped to avoid noise.
@@ -120,3 +130,4 @@ Make sure that you have cache[^8] directory to find licenses from `*.pom` depend
120130
[maven-pom-repos]: https://maven.apache.org/settings.html#repositories
121131
[sbt-dependency-lock]: https://stringbean.github.io/sbt-dependency-lock
122132
[detection-priority]: ../../scanner/vulnerability.md#detection-priority
133+
[version-requirement]: https://maven.apache.org/pom.html#dependency-version-requirement-specification

pkg/dependency/parser/java/pom/artifact.go

+19-2
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,22 @@ import (
66
"regexp"
77
"slices"
88
"strings"
9+
"sync"
910

1011
"github.com/samber/lo"
1112

1213
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
1314
"github.com/aquasecurity/trivy/pkg/log"
15+
"github.com/aquasecurity/trivy/pkg/version/doc"
1416
)
1517

1618
var (
17-
varRegexp = regexp.MustCompile(`\${(\S+?)}`)
19+
varRegexp = regexp.MustCompile(`\${(\S+?)}`)
20+
emptyVersionWarn = sync.OnceFunc(func() {
21+
log.WithPrefix("pom").Warn("Dependency version cannot be determined. Child dependencies will not be found.",
22+
// e.g. https://aquasecurity.github.io/trivy/latest/docs/coverage/language/java/#empty-dependency-version
23+
log.String("details", doc.URL("/docs/coverage/language/java/", "empty-dependency-version")))
24+
})
1825
)
1926

2027
type artifact struct {
@@ -42,7 +49,17 @@ func newArtifact(groupID, artifactID, version string, licenses []string, props m
4249
}
4350

4451
func (a artifact) IsEmpty() bool {
45-
return a.GroupID == "" || a.ArtifactID == "" || a.Version.String() == ""
52+
if a.GroupID == "" || a.ArtifactID == "" {
53+
return true
54+
}
55+
if a.Version.String() == "" {
56+
emptyVersionWarn()
57+
log.WithPrefix("pom").Debug("Dependency version cannot be determined.",
58+
log.String("GroupID", a.GroupID),
59+
log.String("ArtifactID", a.ArtifactID),
60+
)
61+
}
62+
return false
4663
}
4764

4865
func (a artifact) Equal(o artifact) bool {

pkg/dependency/parser/java/pom/parse.go

+8
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,14 @@ func (p *Parser) resolve(art artifact, rootDepManagement []pomDependency) (analy
292292
return *result, nil
293293
}
294294

295+
// We can't resolve a dependency without a version.
296+
// So let's just keep this dependency.
297+
if art.Version.String() == "" {
298+
return analysisResult{
299+
artifact: art,
300+
}, nil
301+
}
302+
295303
p.logger.Debug("Resolving...", log.String("group_id", art.GroupID),
296304
log.String("artifact_id", art.ArtifactID), log.String("version", art.Version.String()))
297305
pomContent, err := p.tryRepository(art.GroupID, art.ArtifactID, art.Version.String())

pkg/dependency/parser/java/pom/parse_test.go

+35
Original file line numberDiff line numberDiff line change
@@ -809,6 +809,17 @@ func TestPom_Parse(t *testing.T) {
809809
Licenses: []string{"Apache 2.0"},
810810
Relationship: ftypes.RelationshipRoot,
811811
},
812+
{
813+
ID: "org.example:example-api",
814+
Name: "org.example:example-api",
815+
Relationship: ftypes.RelationshipDirect,
816+
Locations: []ftypes.Location{
817+
{
818+
StartLine: 28,
819+
EndLine: 32,
820+
},
821+
},
822+
},
812823
},
813824
},
814825
{
@@ -1499,6 +1510,30 @@ func TestPom_Parse(t *testing.T) {
14991510
},
15001511
},
15011512
},
1513+
{
1514+
name: "dependency without version",
1515+
inputFile: filepath.Join("testdata", "dep-without-version", "pom.xml"),
1516+
local: true,
1517+
want: []ftypes.Package{
1518+
{
1519+
ID: "com.example:dep-without-version:1.0.0",
1520+
Name: "com.example:dep-without-version",
1521+
Version: "1.0.0",
1522+
Relationship: ftypes.RelationshipRoot,
1523+
},
1524+
{
1525+
ID: "org.example:example-api",
1526+
Name: "org.example:example-api",
1527+
Relationship: ftypes.RelationshipDirect,
1528+
Locations: ftypes.Locations{
1529+
{
1530+
StartLine: 19,
1531+
EndLine: 22,
1532+
},
1533+
},
1534+
},
1535+
},
1536+
},
15021537
// [INFO] com.example:root-depManagement-in-parent:jar:1.0.0
15031538
// [INFO] \- org.example:example-dependency:jar:2.0.0:compile
15041539
// [INFO] \- org.example:example-api:jar:1.0.1:compile
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3+
<modelVersion>4.0.0</modelVersion>
4+
5+
<name>no-parent</name>
6+
<description>Parent not found</description>
7+
8+
<parent>
9+
<groupId>com.example</groupId>
10+
<artifactId>wrong-parent</artifactId>
11+
<version>1.0.0</version>
12+
</parent>
13+
14+
<groupId>com.example</groupId>
15+
<artifactId>dep-without-version</artifactId>
16+
<version>1.0.0</version>
17+
18+
<dependencies>
19+
<dependency>
20+
<groupId>org.example</groupId>
21+
<artifactId>example-api</artifactId>
22+
</dependency>
23+
</dependencies>
24+
</project>

pkg/fanal/analyzer/language/java/pom/pom_test.go

+11
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,17 @@ func Test_pomAnalyzer_Analyze(t *testing.T) {
147147
Licenses: []string{"Apache-2.0"},
148148
Relationship: types.RelationshipRoot,
149149
},
150+
{
151+
ID: "org.example:example-api",
152+
Name: "org.example:example-api",
153+
Relationship: types.RelationshipDirect,
154+
Locations: []types.Location{
155+
{
156+
StartLine: 21,
157+
EndLine: 25,
158+
},
159+
},
160+
},
150161
},
151162
},
152163
},

0 commit comments

Comments
 (0)