diff --git a/cmd/osv-scanner/internal/helper/getters.go b/cmd/osv-scanner/internal/helper/getters.go index c1fc053e94f..6a894c134a3 100644 --- a/cmd/osv-scanner/internal/helper/getters.go +++ b/cmd/osv-scanner/internal/helper/getters.go @@ -43,6 +43,7 @@ func GetCommonScannerActions(cmd *cli.Command, scanLicensesAllowlist []string) o CompareOffline: cmd.Bool("offline-vulnerabilities"), DownloadDatabases: cmd.Bool("download-offline-databases"), LocalDBPath: cmd.String("local-db-path"), + PluginNetworkDisabled: cmd.Bool("offline"), ScanLicensesSummary: cmd.IsSet("licenses"), ScanLicensesAllowlist: scanLicensesAllowlist, CallAnalysisStates: callAnalysisStates, diff --git a/cmd/osv-scanner/internal/helper/getters_test.go b/cmd/osv-scanner/internal/helper/getters_test.go new file mode 100644 index 00000000000..8dd6f91ee04 --- /dev/null +++ b/cmd/osv-scanner/internal/helper/getters_test.go @@ -0,0 +1,70 @@ +package helper + +import ( + "context" + "testing" + + "github.com/urfave/cli/v3" +) + +func TestGetCommonScannerActions_OfflineFlags(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + args []string + wantCompareOffline bool + wantPluginNetworkDisabled bool + wantNoResolve bool + }{ + { + name: "offline_vulnerabilities_only", + args: []string{"osv-scanner", "--offline-vulnerabilities"}, + wantCompareOffline: true, + wantPluginNetworkDisabled: false, + }, + { + name: "offline_sets_composite_flags", + args: []string{"osv-scanner", "--offline"}, + wantCompareOffline: true, + wantPluginNetworkDisabled: true, + wantNoResolve: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + var actionsCompareOffline bool + var actionsPluginNetworkDisabled bool + var noResolve bool + + cmd := &cli.Command{ + Flags: BuildCommonScanFlags(nil), + Action: func(_ context.Context, cmd *cli.Command) error { + actions := GetCommonScannerActions(cmd, nil) + actionsCompareOffline = actions.CompareOffline + actionsPluginNetworkDisabled = actions.PluginNetworkDisabled + noResolve = cmd.Bool("no-resolve") + + return nil + }, + } + + if err := cmd.Run(context.Background(), tt.args); err != nil { + t.Fatalf("cmd.Run() error = %v", err) + } + + if actionsCompareOffline != tt.wantCompareOffline { + t.Errorf("actions.CompareOffline = %v, want %v", actionsCompareOffline, tt.wantCompareOffline) + } + if actionsPluginNetworkDisabled != tt.wantPluginNetworkDisabled { + t.Errorf("actions.PluginNetworkDisabled = %v, want %v", actionsPluginNetworkDisabled, tt.wantPluginNetworkDisabled) + } + if noResolve != tt.wantNoResolve { + t.Errorf("cmd.Bool(%q) = %v, want %v", "no-resolve", noResolve, tt.wantNoResolve) + } + }) + } +} diff --git a/cmd/osv-scanner/scan/source/__snapshots__/command_test.snap b/cmd/osv-scanner/scan/source/__snapshots__/command_test.snap index dc38e3e7422..b2b9dcb79d7 100755 --- a/cmd/osv-scanner/scan/source/__snapshots__/command_test.snap +++ b/cmd/osv-scanner/scan/source/__snapshots__/command_test.snap @@ -5811,6 +5811,33 @@ No issues found --- +[TestCommand_Transitive/pom.xml_offline_vulnerabilities_keeps_transitive - 1] +Scanning dir ./testdata/maven-transitive/pom.xml +Scanned /testdata/maven-transitive/pom.xml file and found 1 package +Warning: enricher transitivedependency/pomxml may be risky when run on untrusted artifacts. Please ensure you trust the source code and artifacts. +Loaded Maven local db from /osv-scanner/Maven/all.zip + +Total 1 package affected by 7 known vulnerabilities (2 Critical, 1 High, 4 Medium, 0 Low, 0 Unknown) from 1 ecosystem. +7 vulnerabilities can be fixed. + ++-------------------------------------+------+-----------+-------------------------------------+---------+---------------+-----------------------------------+ +| OSV URL | CVSS | ECOSYSTEM | PACKAGE | VERSION | FIXED VERSION | SOURCE | ++-------------------------------------+------+-----------+-------------------------------------+---------+---------------+-----------------------------------+ +| https://osv.dev/GHSA-3pxv-7cmr-fjr4 | 6.9 | Maven | org.apache.logging.log4j:log4j-core | 2.14.1 | 2.25.4 | testdata/maven-transitive/pom.xml | +| https://osv.dev/GHSA-6hg6-v5c8-fphq | 6.3 | Maven | org.apache.logging.log4j:log4j-core | 2.14.1 | 2.25.4 | testdata/maven-transitive/pom.xml | +| https://osv.dev/GHSA-7rjr-3q55-vv33 | 9.0 | Maven | org.apache.logging.log4j:log4j-core | 2.14.1 | 2.16.0 | testdata/maven-transitive/pom.xml | +| https://osv.dev/GHSA-8489-44mv-ggj8 | 6.6 | Maven | org.apache.logging.log4j:log4j-core | 2.14.1 | 2.17.1 | testdata/maven-transitive/pom.xml | +| https://osv.dev/GHSA-jfh8-c2jp-5v3q | 10.0 | Maven | org.apache.logging.log4j:log4j-core | 2.14.1 | 2.15.0 | testdata/maven-transitive/pom.xml | +| https://osv.dev/GHSA-p6xc-xr62-6r2g | 8.6 | Maven | org.apache.logging.log4j:log4j-core | 2.14.1 | 2.17.0 | testdata/maven-transitive/pom.xml | +| https://osv.dev/GHSA-vc5p-v9hr-52mj | 6.3 | Maven | org.apache.logging.log4j:log4j-core | 2.14.1 | 2.25.3 | testdata/maven-transitive/pom.xml | ++-------------------------------------+------+-----------+-------------------------------------+---------+---------------+-----------------------------------+ + +--- + +[TestCommand_Transitive/pom.xml_offline_vulnerabilities_keeps_transitive - 2] + +--- + [TestCommand_Transitive/pom.xml_transitive_default - 1] Scanning dir ./testdata/maven-transitive/pom.xml Scanned /testdata/maven-transitive/pom.xml file and found 1 package diff --git a/cmd/osv-scanner/scan/source/command_test.go b/cmd/osv-scanner/scan/source/command_test.go index 7f0e289260e..8745bc9122e 100644 --- a/cmd/osv-scanner/scan/source/command_test.go +++ b/cmd/osv-scanner/scan/source/command_test.go @@ -1348,6 +1348,11 @@ func TestCommand_Transitive(t *testing.T) { // Direct dependencies do not have any vulnerability. Exit: 0, }, + { + Name: "pom.xml_offline_vulnerabilities_keeps_transitive", + Args: []string{"", "source", "--offline-vulnerabilities", "--download-offline-databases", "./testdata/maven-transitive/pom.xml"}, + Exit: 1, + }, { Name: "pom.xml_enricher_requires_extractor", Args: []string{"", "source", "--experimental-disable-plugins=java/pomxml", "./testdata/maven-transitive/abc.xml"}, diff --git a/pkg/osvscanner/osvscanner.go b/pkg/osvscanner/osvscanner.go index 73b5ec051de..1dc0848989b 100644 --- a/pkg/osvscanner/osvscanner.go +++ b/pkg/osvscanner/osvscanner.go @@ -57,6 +57,9 @@ type ScannerActions struct { DownloadDatabases bool LocalDBPath string + // network-backed plugins + PluginNetworkDisabled bool + // license scanning ScanLicensesSummary bool ScanLicensesAllowlist []string @@ -304,15 +307,11 @@ func DoContainerScan(actions ScannerActions) (models.VulnerabilityResults, error capabilities := &plugin.Capabilities{ DirectFS: true, RunningSystem: false, - Network: plugin.NetworkOnline, + Network: networkCapability(actions), OS: plugin.OSLinux, AllowUnsafePlugins: true, } - if actions.CompareOffline { - capabilities.Network = plugin.NetworkOffline - } - plugins = plugin.FilterByCapabilities(plugins, capabilities) // --- Do Scalibr Scan --- diff --git a/pkg/osvscanner/scan.go b/pkg/osvscanner/scan.go index 51e2f779f01..f53fb572cab 100644 --- a/pkg/osvscanner/scan.go +++ b/pkg/osvscanner/scan.go @@ -96,6 +96,14 @@ func getPlugins(defaultPlugins []string, accessors ExternalAccessors, actions Sc return plugins } +func networkCapability(actions ScannerActions) plugin.Network { + if actions.PluginNetworkDisabled { + return plugin.NetworkOffline + } + + return plugin.NetworkOnline +} + // countNotEnrichers counts the number of plugins that are not enricher.Enricher plugins func countNotEnrichers(plugins []plugin.Plugin) int { count := 0 @@ -220,15 +228,11 @@ SBOMLoop: capabilities := plugin.Capabilities{ DirectFS: true, RunningSystem: true, - Network: plugin.NetworkOnline, + Network: networkCapability(actions), OS: osCapability, AllowUnsafePlugins: true, } - if actions.CompareOffline { - capabilities.Network = plugin.NetworkOffline - } - filteredPlugins := append(plugin.FilterByCapabilities(plugins, &capabilities), gitDirectPlugin) // For each root, run scalibr's scan() once. diff --git a/pkg/osvscanner/scan_test.go b/pkg/osvscanner/scan_test.go index de497952c81..4b413900fee 100644 --- a/pkg/osvscanner/scan_test.go +++ b/pkg/osvscanner/scan_test.go @@ -3,8 +3,57 @@ package osvscanner import ( "path/filepath" "testing" + + "github.com/google/osv-scalibr/plugin" ) +func Test_networkCapability(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + actions ScannerActions + want plugin.Network + }{ + { + name: "default_online", + want: plugin.NetworkOnline, + }, + { + name: "offline_vulnerabilities_keeps_network_online", + actions: ScannerActions{ + CompareOffline: true, + }, + want: plugin.NetworkOnline, + }, + { + name: "plugin_network_disabled_sets_network_offline", + actions: ScannerActions{ + PluginNetworkDisabled: true, + }, + want: plugin.NetworkOffline, + }, + { + name: "full_offline_sets_network_offline", + actions: ScannerActions{ + CompareOffline: true, + PluginNetworkDisabled: true, + }, + want: plugin.NetworkOffline, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + if got := networkCapability(tt.actions); got != tt.want { + t.Errorf("networkCapability(%+v) = %v, want %v", tt.actions, got, tt.want) + } + }) + } +} + func Test_isDescendent(t *testing.T) { t.Parallel()