@@ -6,15 +6,12 @@ import (
6
6
"io"
7
7
"os"
8
8
"path/filepath"
9
- "strings"
10
9
11
10
"github.com/google/osv-scanner/v2/cmd/osv-scanner/internal/helper"
12
- "github.com/google/osv-scanner/v2/internal/spdx"
13
11
"github.com/google/osv-scanner/v2/pkg/models"
14
12
"github.com/google/osv-scanner/v2/pkg/osvscanner"
15
13
"github.com/google/osv-scanner/v2/pkg/reporter"
16
14
"github.com/urfave/cli/v2"
17
- "golang.org/x/term"
18
15
)
19
16
20
17
var projectScanFlags = []cli.Flag {
@@ -45,11 +42,6 @@ var projectScanFlags = []cli.Flag{
45
42
Usage : "check subdirectories" ,
46
43
Value : false ,
47
44
},
48
- & cli.BoolFlag {
49
- Name : "experimental-call-analysis" ,
50
- Usage : "[Deprecated] attempt call analysis on code to detect only active vulnerabilities" ,
51
- Value : false ,
52
- },
53
45
& cli.BoolFlag {
54
46
Name : "no-ignore" ,
55
47
Usage : "also scan files that would be ignored by .gitignore" ,
@@ -63,6 +55,9 @@ var projectScanFlags = []cli.Flag{
63
55
Name : "no-call-analysis" ,
64
56
Usage : "disables call graph analysis" ,
65
57
},
58
+ }
59
+
60
+ var projectScanExperimentalFlags = []cli.Flag {
66
61
& cli.StringFlag {
67
62
Name : "experimental-resolution-data-source" ,
68
63
Usage : "source to fetch package information from; value can be: deps.dev, native" ,
@@ -79,14 +74,25 @@ var projectScanFlags = []cli.Flag{
79
74
Name : "experimental-maven-registry" ,
80
75
Usage : "URL of the default registry to fetch Maven metadata" ,
81
76
},
77
+ & cli.BoolFlag {
78
+ Name : "experimental-call-analysis" ,
79
+ Usage : "[Deprecated] attempt call analysis on code to detect only active vulnerabilities" ,
80
+ Value : false ,
81
+ },
82
82
}
83
83
84
84
func Command (stdout , stderr io.Writer , r * reporter.Reporter ) * cli.Command {
85
+ flags := make ([]cli.Flag , 0 , len (projectScanFlags )+ len (helper .GlobalScanFlags )+ len (projectScanExperimentalFlags ))
86
+ flags = append (flags , projectScanFlags ... )
87
+ flags = append (flags , helper .GlobalScanFlags ... )
88
+ // Make sure all experimental flags show after regular flags
89
+ flags = append (flags , projectScanExperimentalFlags ... )
90
+
85
91
return & cli.Command {
86
92
Name : "source" ,
87
93
Usage : "scans a source project's dependencies for known vulnerabilities using the OSV database." ,
88
94
Description : "scans a source project's dependencies for known vulnerabilities using the OSV database." ,
89
- Flags : append ( projectScanFlags , helper . GlobalScanFlags ... ) ,
95
+ Flags : flags ,
90
96
ArgsUsage : "[directory1 directory2...]" ,
91
97
Action : func (c * cli.Context ) error {
92
98
var err error
@@ -122,43 +128,14 @@ func Action(context *cli.Context, stdout, stderr io.Writer) (reporter.Reporter,
122
128
}
123
129
}
124
130
125
- termWidth := 0
126
- var err error
127
- if outputPath != "" { // Output is definitely a file
128
- stdout , err = os .Create (outputPath )
129
- if err != nil {
130
- return nil , fmt .Errorf ("failed to create output file: %w" , err )
131
- }
132
- } else { // Output might be a terminal
133
- if stdoutAsFile , ok := stdout .(* os.File ); ok {
134
- termWidth , _ , err = term .GetSize (int (stdoutAsFile .Fd ()))
135
- if err != nil { // If output is not a terminal,
136
- termWidth = 0
137
- }
138
- }
139
- }
140
-
141
- if context .Bool ("experimental-licenses-summary" ) && context .IsSet ("experimental-licenses" ) {
142
- return nil , errors .New ("--experimental-licenses-summary and --experimental-licenses flags cannot be set" )
143
- }
144
- allowlist := context .StringSlice ("experimental-licenses" )
145
- if context .IsSet ("experimental-licenses" ) {
146
- if len (allowlist ) == 0 ||
147
- (len (allowlist ) == 1 && allowlist [0 ] == "" ) {
148
- return nil , errors .New ("--experimental-licenses requires at least one value" )
149
- }
150
- if unrecognized := spdx .Unrecognized (allowlist ); len (unrecognized ) > 0 {
151
- return nil , fmt .Errorf ("--experimental-licenses requires comma-separated spdx licenses. The following license(s) are not recognized as spdx: %s" , strings .Join (unrecognized , "," ))
152
- }
153
- }
154
-
155
- verbosityLevel , err := reporter .ParseVerbosityLevel (context .String ("verbosity" ))
131
+ r , err := helper .GetReporter (context , stdout , stderr , outputPath , format )
156
132
if err != nil {
157
133
return nil , err
158
134
}
159
- r , err := reporter .New (format , stdout , stderr , verbosityLevel , termWidth )
135
+
136
+ scanLicensesAllowlist , err := helper .GetScanLicensesAllowlist (context )
160
137
if err != nil {
161
- return r , err
138
+ return nil , err
162
139
}
163
140
164
141
var callAnalysisStates map [string ]bool
@@ -169,38 +146,24 @@ func Action(context *cli.Context, stdout, stderr io.Writer) (reporter.Reporter,
169
146
callAnalysisStates = helper .CreateCallAnalysisStates (context .StringSlice ("call-analysis" ), context .StringSlice ("no-call-analysis" ))
170
147
}
171
148
172
- scanLicensesAllowlist := context .StringSlice ("experimental-licenses" )
173
- if context .Bool ("experimental-offline" ) {
174
- scanLicensesAllowlist = []string {}
149
+ experimentalScannerActions := helper .GetExperimentalScannerActions (context , scanLicensesAllowlist )
150
+ // Add `source` specific experimental configs
151
+ experimentalScannerActions .TransitiveScanningActions = osvscanner.TransitiveScanningActions {
152
+ Disabled : context .Bool ("experimental-no-resolve" ),
153
+ NativeDataSource : context .String ("experimental-resolution-data-source" ) == "native" ,
154
+ MavenRegistry : context .String ("experimental-maven-registry" ),
175
155
}
176
156
177
157
scannerAction := osvscanner.ScannerActions {
178
- LockfilePaths : context .StringSlice ("lockfile" ),
179
- SBOMPaths : context .StringSlice ("sbom" ),
180
- Recursive : context .Bool ("recursive" ),
181
- SkipGit : context .Bool ("skip-git" ),
182
- NoIgnore : context .Bool ("no-ignore" ),
183
- ConfigOverridePath : context .String ("config" ),
184
- DirectoryPaths : context .Args ().Slice (),
185
- CallAnalysisStates : callAnalysisStates ,
186
- ExperimentalScannerActions : osvscanner.ExperimentalScannerActions {
187
- LocalDBPath : context .String ("experimental-local-db-path" ),
188
- DownloadDatabases : context .Bool ("experimental-download-offline-databases" ),
189
- CompareOffline : context .Bool ("experimental-offline-vulnerabilities" ),
190
- // License summary mode causes all
191
- // packages to appear in the json as
192
- // every package has a license - even
193
- // if it's just the UNKNOWN license.
194
- ShowAllPackages : context .Bool ("experimental-all-packages" ) ||
195
- context .Bool ("experimental-licenses-summary" ),
196
- ScanLicensesSummary : context .Bool ("experimental-licenses-summary" ),
197
- ScanLicensesAllowlist : scanLicensesAllowlist ,
198
- TransitiveScanningActions : osvscanner.TransitiveScanningActions {
199
- Disabled : context .Bool ("experimental-no-resolve" ),
200
- NativeDataSource : context .String ("experimental-resolution-data-source" ) == "native" ,
201
- MavenRegistry : context .String ("experimental-maven-registry" ),
202
- },
203
- },
158
+ LockfilePaths : context .StringSlice ("lockfile" ),
159
+ SBOMPaths : context .StringSlice ("sbom" ),
160
+ Recursive : context .Bool ("recursive" ),
161
+ SkipGit : context .Bool ("skip-git" ),
162
+ NoIgnore : context .Bool ("no-ignore" ),
163
+ ConfigOverridePath : context .String ("config" ),
164
+ DirectoryPaths : context .Args ().Slice (),
165
+ CallAnalysisStates : callAnalysisStates ,
166
+ ExperimentalScannerActions : experimentalScannerActions ,
204
167
}
205
168
206
169
var vulnResult models.VulnerabilityResults
0 commit comments