diff --git a/docs/docs/coverage/language/java.md b/docs/docs/coverage/language/java.md index f30c5cb05b85..59a9ba571506 100644 --- a/docs/docs/coverage/language/java.md +++ b/docs/docs/coverage/language/java.md @@ -55,6 +55,14 @@ The vulnerability database will be downloaded anyway. !!! Warning Trivy may skip some dependencies (that were not found on your local machine) when the `--offline-scan` flag is passed. + +### maven-invoker-plugin +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. + +Trivy marks dependencies from these files as the development dependencies and skip them by default. +If you need to show them, use the `--include-dev-deps` flag. + + ## Gradle.lock `gradle.lock` files contain all necessary information about used dependencies. Trivy simply parses the file, extract dependencies, and finds vulnerabilities for them. @@ -69,4 +77,5 @@ It doesn't require the internet access. [^6]: `/Users//.m2/repository` (for Linux and Mac) and `C:/Users//.m2/repository` (for Windows) by default [^7]: To avoid confusion, Trivy only finds locations for direct dependencies from the base pom.xml file. -[dependency-graph]: ../../configuration/reporting.md#show-origins-of-vulnerable-dependencies \ No newline at end of file +[dependency-graph]: ../../configuration/reporting.md#show-origins-of-vulnerable-dependencies +[maven-invoker-plugin]: https://maven.apache.org/plugins/maven-invoker-plugin/usage.html \ No newline at end of file diff --git a/pkg/fanal/analyzer/language/java/pom/pom.go b/pkg/fanal/analyzer/language/java/pom/pom.go index 9ad7a118cb88..d192d69dfc07 100644 --- a/pkg/fanal/analyzer/language/java/pom/pom.go +++ b/pkg/fanal/analyzer/language/java/pom/pom.go @@ -4,6 +4,7 @@ import ( "context" "os" "path/filepath" + "strings" "golang.org/x/xerrors" @@ -23,11 +24,22 @@ const version = 1 type pomAnalyzer struct{} func (a pomAnalyzer) Analyze(_ context.Context, input analyzer.AnalysisInput) (*analyzer.AnalysisResult, error) { - p := pom.NewParser(filepath.Join(input.Dir, input.FilePath), pom.WithOffline(input.Options.Offline)) + filePath := filepath.Join(input.Dir, input.FilePath) + p := pom.NewParser(filePath, pom.WithOffline(input.Options.Offline)) res, err := language.Analyze(types.Pom, input.FilePath, input.Content, p) if err != nil { return nil, xerrors.Errorf("%s parse error: %w", input.FilePath, err) } + + // Mark integration test pom files for `maven-invoker-plugin` as Dev to skip them by default. + if isIntegrationTestDir(filePath) { + for i := range res.Applications { + for j := range res.Applications[i].Libraries { + res.Applications[i].Libraries[j].Dev = true + } + } + } + return res, nil } @@ -42,3 +54,14 @@ func (a pomAnalyzer) Type() analyzer.Type { func (a pomAnalyzer) Version() int { return version } + +// isIntegrationTestDir checks that pom file is in directory with integration tests of `maven-invoker-plugin` +// https://maven.apache.org/plugins/maven-invoker-plugin/usage.html +func isIntegrationTestDir(filePath string) bool { + dirs := strings.Split(filepath.ToSlash(filePath), "/") + // filepath pattern: `**/[src|target]/it/*/pom.xml` + if len(dirs) < 4 { + return false + } + return (dirs[len(dirs)-4] == "src" || dirs[len(dirs)-4] == "target") && dirs[len(dirs)-3] == "it" +} diff --git a/pkg/fanal/analyzer/language/java/pom/pom_test.go b/pkg/fanal/analyzer/language/java/pom/pom_test.go index 10cec453b863..6df1ea2274fc 100644 --- a/pkg/fanal/analyzer/language/java/pom/pom_test.go +++ b/pkg/fanal/analyzer/language/java/pom/pom_test.go @@ -89,6 +89,42 @@ func Test_pomAnalyzer_Analyze(t *testing.T) { }, }, }, + { + name: "happy path for maven-invoker-plugin integration tests", + inputFile: "testdata/mark-as-dev/src/it/example/pom.xml", + want: &analyzer.AnalysisResult{ + Applications: []types.Application{ + { + Type: types.Pom, + FilePath: "testdata/mark-as-dev/src/it/example/pom.xml", + Libraries: types.Packages{ + { + ID: "com.example:example-api:@example.version@", + Name: "com.example:example-api", + Version: "@example.version@", + Locations: []types.Location{ + { + StartLine: 28, + EndLine: 32, + }, + }, + Dev: true, + }, + { + ID: "com.example:example:1.0.0", + Name: "com.example:example", + Version: "1.0.0", + Licenses: []string{"Apache-2.0"}, + DependsOn: []string{ + "com.example:example-api:@example.version@", + }, + Dev: true, + }, + }, + }, + }, + }, + }, { name: "unsupported requirement", inputFile: "testdata/requirements/pom.xml", diff --git a/pkg/fanal/analyzer/language/java/pom/testdata/mark-as-dev/src/it/example/pom.xml b/pkg/fanal/analyzer/language/java/pom/testdata/mark-as-dev/src/it/example/pom.xml new file mode 100644 index 000000000000..3717c917a1f2 --- /dev/null +++ b/pkg/fanal/analyzer/language/java/pom/testdata/mark-as-dev/src/it/example/pom.xml @@ -0,0 +1,34 @@ + + 4.0.0 + + com.example + example + 1.0.0 + + example + Example + + + + Apache 2.0 + http://www.apache.org/licenses/LICENSE-2.0.html + repo + + + + + + knqyf263 + https://github.com/knqyf263 + + + + + + com.example + example-api + @example.version@ + + +