Skip to content

Commit 3ff97a7

Browse files
committed
feature: Only consider specific files for Trivy CF-1742
1 parent 6487f96 commit 3ff97a7

File tree

8 files changed

+120
-40
lines changed

8 files changed

+120
-40
lines changed

plugins/runtime-utils_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,21 +69,21 @@ func TestProcessRuntimes(t *testing.T) {
6969
// Assert the download URL is correctly formatted
7070
expectedDownloadURL := "https://nodejs.org/dist/v18.17.1/" + expectedFileName + "." + expectedExtension
7171
assert.Equal(t, expectedDownloadURL, nodeInfo.DownloadURL)
72-
72+
7373
// Assert binary paths are correctly set
7474
assert.NotNil(t, nodeInfo.Binaries)
7575
assert.Greater(t, len(nodeInfo.Binaries), 0)
76-
76+
7777
// Check if node and npm binaries are present
7878
nodeBinary := nodeInfo.InstallDir + "/bin/node"
7979
npmBinary := nodeInfo.InstallDir + "/bin/npm"
80-
80+
8181
// Add .exe extension for Windows
8282
if runtime.GOOS == "windows" {
8383
nodeBinary += ".exe"
8484
npmBinary += ".exe"
8585
}
86-
86+
8787
assert.Equal(t, nodeBinary, nodeInfo.Binaries["node"])
8888
assert.Equal(t, npmBinary, nodeInfo.Binaries["npm"])
8989
}

plugins/tool-utils.go

Lines changed: 33 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -55,18 +55,19 @@ type RuntimeBinaries struct {
5555

5656
// ToolPluginConfig holds the structure of the tool plugin.yaml file
5757
type ToolPluginConfig struct {
58-
Name string `yaml:"name"`
59-
Description string `yaml:"description"`
60-
DefaultVersion string `yaml:"default_version"`
61-
Runtime string `yaml:"runtime"`
62-
RuntimeBinaries RuntimeBinaries `yaml:"runtime_binaries"`
63-
Installation InstallationConfig `yaml:"installation"`
64-
Download DownloadConfig `yaml:"download"`
65-
Environment map[string]string `yaml:"environment"`
66-
Binaries []ToolBinary `yaml:"binaries"`
67-
Formatters []Formatter `yaml:"formatters"`
68-
OutputOptions OutputOptions `yaml:"output_options"`
69-
AnalysisOptions AnalysisOptions `yaml:"analysis_options"`
58+
Name string `yaml:"name"`
59+
Description string `yaml:"description"`
60+
DefaultVersion string `yaml:"default_version"`
61+
SupportsSpecificFiles bool `yaml:"support_specific_files"`
62+
Runtime string `yaml:"runtime"`
63+
RuntimeBinaries RuntimeBinaries `yaml:"runtime_binaries"`
64+
Installation InstallationConfig `yaml:"installation"`
65+
Download DownloadConfig `yaml:"download"`
66+
Environment map[string]string `yaml:"environment"`
67+
Binaries []ToolBinary `yaml:"binaries"`
68+
Formatters []Formatter `yaml:"formatters"`
69+
OutputOptions OutputOptions `yaml:"output_options"`
70+
AnalysisOptions AnalysisOptions `yaml:"analysis_options"`
7071
}
7172

7273
// ToolConfig represents configuration for a tool
@@ -78,15 +79,16 @@ type ToolConfig struct {
7879

7980
// ToolInfo contains all processed information about a tool
8081
type ToolInfo struct {
81-
Name string
82-
Version string
83-
Runtime string
84-
InstallDir string
85-
Binaries map[string]string // Map of binary name to full path
86-
Formatters map[string]string // Map of formatter name to flag
87-
OutputFlag string
88-
AutofixFlag string
89-
DefaultPath string
82+
Name string
83+
Version string
84+
Runtime string
85+
InstallDir string
86+
Binaries map[string]string // Map of binary name to full path
87+
Formatters map[string]string // Map of formatter name to flag
88+
OutputFlag string
89+
AutofixFlag string
90+
DefaultPath string
91+
SupportsSpecificFiles bool // Whether tool supports specific file analysis
9092
// Runtime binaries
9193
PackageManager string
9294
ExecutionBinary string
@@ -135,15 +137,16 @@ func ProcessTools(configs []ToolConfig, toolDir string, runtimes map[string]*Run
135137
}
136138
// Create ToolInfo with basic information
137139
info := &ToolInfo{
138-
Name: config.Name,
139-
Version: config.Version,
140-
Runtime: toolRuntime,
141-
InstallDir: installDir,
142-
Binaries: make(map[string]string),
143-
Formatters: make(map[string]string),
144-
OutputFlag: pluginConfig.OutputOptions.FileFlag,
145-
AutofixFlag: pluginConfig.AnalysisOptions.AutofixFlag,
146-
DefaultPath: pluginConfig.AnalysisOptions.DefaultPath,
140+
Name: config.Name,
141+
Version: config.Version,
142+
Runtime: toolRuntime,
143+
InstallDir: installDir,
144+
Binaries: make(map[string]string),
145+
Formatters: make(map[string]string),
146+
OutputFlag: pluginConfig.OutputOptions.FileFlag,
147+
AutofixFlag: pluginConfig.AnalysisOptions.AutofixFlag,
148+
DefaultPath: pluginConfig.AnalysisOptions.DefaultPath,
149+
SupportsSpecificFiles: pluginConfig.SupportsSpecificFiles,
147150
// Store runtime binary information
148151
PackageManager: pluginConfig.RuntimeBinaries.PackageManager,
149152
ExecutionBinary: pluginConfig.RuntimeBinaries.Execution,

plugins/tool-utils_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ func TestProcessTools(t *testing.T) {
6666
// Assert installation command templates are correctly set
6767
assert.Equal(t, "install --prefix {{.InstallDir}} {{.PackageName}}@{{.Version}} @microsoft/eslint-formatter-sarif", eslintInfo.InstallCommand)
6868
assert.Equal(t, "config set registry {{.Registry}}", eslintInfo.RegistryCommand)
69+
70+
// Assert that eslint does not support specific files (default false)
71+
assert.False(t, eslintInfo.SupportsSpecificFiles, "eslint should not support specific files")
6972
}
7073

7174
func TestProcessToolsWithDownload(t *testing.T) {
@@ -120,6 +123,9 @@ func TestProcessToolsWithDownload(t *testing.T) {
120123
trivyBinary := filepath.Join(expectedInstallDir, "trivy")
121124
assert.Equal(t, trivyBinary, trivyInfo.Binaries["trivy"])
122125

126+
// Assert that trivy supports specific files (from plugin.yaml)
127+
assert.True(t, trivyInfo.SupportsSpecificFiles, "trivy should support specific files")
128+
123129
// Verify URL components
124130
assert.Contains(t, trivyInfo.DownloadURL, "aquasecurity/trivy/releases/download")
125131
assert.Contains(t, trivyInfo.DownloadURL, trivyInfo.Version)
@@ -199,3 +205,47 @@ func TestGetSupportedTools(t *testing.T) {
199205
})
200206
}
201207
}
208+
209+
func TestGetToolConfig(t *testing.T) {
210+
pluginManager := GetPluginManager()
211+
212+
tests := []struct {
213+
name string
214+
toolName string
215+
expectedSupportsSpecificFiles bool
216+
expectedError bool
217+
}{
218+
{
219+
name: "trivy should support specific files",
220+
toolName: "trivy",
221+
expectedSupportsSpecificFiles: true,
222+
expectedError: false,
223+
},
224+
{
225+
name: "eslint should not support specific files",
226+
toolName: "eslint",
227+
expectedSupportsSpecificFiles: false,
228+
expectedError: false,
229+
},
230+
{
231+
name: "non-existent tool should return error",
232+
toolName: "non-existent-tool",
233+
expectedError: true,
234+
},
235+
}
236+
237+
for _, tt := range tests {
238+
t.Run(tt.name, func(t *testing.T) {
239+
config, err := pluginManager.GetToolConfig(tt.toolName)
240+
241+
if tt.expectedError {
242+
assert.Error(t, err)
243+
return
244+
}
245+
246+
assert.NoError(t, err)
247+
assert.Equal(t, tt.expectedSupportsSpecificFiles, config.SupportsSpecificFiles,
248+
"SupportsSpecificFiles should match expected value for %s", tt.toolName)
249+
})
250+
}
251+
}

plugins/tools/pylint/test/src/.codacy/tools-configs/languages-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ tools:
22
- name: pylint
33
languages: [Python]
44
extensions: [.py]
5-
files: [Pipfile.lock, poetry.lock, requirements.txt, uv.lock]
5+
files: []

plugins/tools/trivy/plugin.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
name: trivy
22
description: Trivy is a comprehensive security scanner for containers and other artifacts.
33
default_version: 0.59.1
4+
support_specific_files: true
45
download:
56
url_template: "https://github.com/aquasecurity/trivy/releases/download/v{{.Version}}/trivy_{{.Version}}_{{.OS}}-{{.Arch}}.{{.Extension}}"
67
file_name_template: "trivy_{{.Version}}_{{.OS}}_{{.Arch}}"
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
tools:
2+
- name: trivy
3+
languages: [C, CPP, CSharp, Dart, Dockerfile, Elixir, Go, JSON, Java, Javascript, PHP, Python, Ruby, Rust, Scala, Swift, Terraform, TypeScript, XML, YAML]
4+
extensions: [.c, .cc, .cpp, .cs, .cxx, .dart, .dockerfile, .ex, .exs, .gemspec, .go, .h, .hpp, .ino, .java, .jbuilder, .js, .jsm, .json, .jsx, .mjs, .opal, .php, .podspec, .pom, .py, .rake, .rb, .rlib, .rs, .scala, .swift, .tf, .ts, .tsx, .vue, .wsdl, .xml, .xsl, .yaml, .yml]
5+
files: [.deps.json, Berksfile, Capfile, Cargo.lock, Cheffile, Directory.Packages.props, Dockerfile, Fastfile, Gemfile, Gemfile.lock, Guardfile, Package.resolved, Packages.props, Pipfile.lock, Podfile, Podfile.lock, Rakefile, Thorfile, Vagabondfile, Vagrantfile, build.sbt.lock, composer.lock, conan.lock, config.ru, go.mod, gradle.lockfile, mix.lock, package-lock.json, package.json, packages.config, packages.lock.json, pnpm-lock.yaml, poetry.lock, pom.xml, pubspec.lock, requirements.txt, uv.lock, yarn.lock]
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
severity:
2+
- LOW
3+
- MEDIUM
4+
- HIGH
5+
- CRITICAL
6+
7+
scan:
8+
scanners:
9+
- vuln
10+
- secret

tools/language_config.go

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,16 +82,23 @@ func buildToolLanguageInfoFromAPI() (map[string]domain.ToolLanguageInfo, error)
8282
extensionsSet := make(map[string]struct{})
8383
filesSet := make(map[string]struct{})
8484

85+
// Check if this tool supports specific files
86+
toolInfo := config.Config.Tools()[toolName]
87+
supportsSpecificFiles := toolInfo != nil && toolInfo.SupportsSpecificFiles
88+
8589
for _, apiLang := range tool.Languages {
8690
lowerLang := strings.ToLower(apiLang)
8791
if extensions, exists := languageExtensionsMap[lowerLang]; exists {
8892
for _, ext := range extensions {
8993
extensionsSet[ext] = struct{}{}
9094
}
9195
}
92-
if files, exists := languageFilesMap[lowerLang]; exists {
93-
for _, file := range files {
94-
filesSet[file] = struct{}{}
96+
// Only populate files if the tool supports specific files
97+
if supportsSpecificFiles {
98+
if files, exists := languageFilesMap[lowerLang]; exists {
99+
for _, file := range files {
100+
filesSet[file] = struct{}{}
101+
}
95102
}
96103
}
97104
}
@@ -244,12 +251,16 @@ func buildRemoteModeLanguagesConfig(apiTools []domain.Tool, toolIDMap map[string
244251
extensionsSet := make(map[string]struct{})
245252
filesSet := make(map[string]struct{})
246253

254+
// Check if this tool supports specific files
255+
toolInfo := config.Config.Tools()[shortName]
256+
supportsSpecificFiles := toolInfo != nil && toolInfo.SupportsSpecificFiles
257+
247258
for _, lang := range tool.Languages {
248259
lowerLang := strings.ToLower(lang)
249260
if repoLang, exists := repositoryLanguages[lowerLang]; exists {
250261
// Check if this language has either extensions or files
251262
hasExtensions := len(repoLang.Extensions) > 0
252-
hasFiles := len(repoLang.Files) > 0
263+
hasFiles := len(repoLang.Files) > 0 && supportsSpecificFiles
253264

254265
if hasExtensions || hasFiles {
255266
configTool.Languages = append(configTool.Languages, lang)
@@ -261,7 +272,7 @@ func buildRemoteModeLanguagesConfig(apiTools []domain.Tool, toolIDMap map[string
261272
}
262273
}
263274

264-
// Add repository-specific files if they exist
275+
// Add repository-specific files if they exist (only if tool supports it)
265276
if hasFiles {
266277
for _, file := range repoLang.Files {
267278
filesSet[file] = struct{}{}

0 commit comments

Comments
 (0)