diff --git a/cmd/osv-scanner/internal/helper/flags.go b/cmd/osv-scanner/internal/helper/flags.go index c7601c2906f..60c91e543ce 100644 --- a/cmd/osv-scanner/internal/helper/flags.go +++ b/cmd/osv-scanner/internal/helper/flags.go @@ -191,20 +191,57 @@ func BuildCommonScanFlags(defaultExtractors []string) []cli.Flag { Value: &allowedLicencesFlag{}, }, &cli.BoolFlag{ - Name: "experimental-flag-deprecated-packages", + Name: "x-flag-deprecated-packages", Usage: "report if package versions are deprecated", }, + &cli.BoolFlag{ + Name: "experimental-flag-deprecated-packages", + Usage: "[DEPRECATED] (use \"--x-flag-deprecated-packages\" instead) report if package versions are deprecated", + Action: func(_ context.Context, _ *cli.Command, _ bool) error { + cmdlogger.Warnf("Warning: --experimental-flag-deprecated-packages has been deprecated in favor of --x-flag-deprecated-packages") + + return nil + }, + }, &cli.StringSliceFlag{ Name: "experimental-plugins", + Usage: "[DEPRECATED] (use \"--x-plugins\" instead) list of specific plugins and presets of plugins to use", + Action: func(_ context.Context, _ *cli.Command, _ []string) error { + cmdlogger.Warnf("Warning: --experimental-plugins has been deprecated in favor of --x-plugins") + + return nil + }, + Value: defaultExtractors, + }, + &cli.StringSliceFlag{ + Name: "x-plugins", Usage: "list of specific plugins and presets of plugins to use", Value: defaultExtractors, }, &cli.StringSliceFlag{ Name: "experimental-disable-plugins", + Usage: "[DEPRECATED] (use \"--x-disable-plugins\" instead) list of specific plugins and presets of plugins to not use", + Action: func(_ context.Context, _ *cli.Command, _ []string) error { + cmdlogger.Warnf("Warning: --experimental-disable-plugins has been deprecated in favor of --x-disable-plugins") + + return nil + }, + }, + &cli.StringSliceFlag{ + Name: "x-disable-plugins", Usage: "list of specific plugins and presets of plugins to not use", }, &cli.BoolFlag{ Name: "experimental-no-default-plugins", + Usage: "[DEPRECATED] (use \"--x-no-default-plugins\" instead) disable default plugins, instead using only those enabled by --x-plugins", + Action: func(_ context.Context, _ *cli.Command, _ bool) error { + cmdlogger.Warnf("Warning: --experimental-no-default-plugins has been deprecated in favor of --x-no-default-plugins") + + return nil + }, + }, + &cli.BoolFlag{ + Name: "x-no-default-plugins", Usage: "disable default plugins, instead using only those enabled by --experimental-plugins", }, } diff --git a/cmd/osv-scanner/internal/helper/getters.go b/cmd/osv-scanner/internal/helper/getters.go index c1fc053e94f..d72373de44b 100644 --- a/cmd/osv-scanner/internal/helper/getters.go +++ b/cmd/osv-scanner/internal/helper/getters.go @@ -49,12 +49,22 @@ func GetCommonScannerActions(cmd *cli.Command, scanLicensesAllowlist []string) o } } +// FallbackToDeprecatedName returns the preferred cli flag name if set, +// otherwise falling back to the deprecated name +func FallbackToDeprecatedName(cmd *cli.Command, name, old string) string { + if cmd.IsSet(name) { + return name + } + + return old +} + func GetExperimentalScannerActions(cmd *cli.Command, client *http.Client) osvscanner.ExperimentalScannerActions { return osvscanner.ExperimentalScannerActions{ - PluginsEnabled: cmd.StringSlice("experimental-plugins"), - PluginsDisabled: cmd.StringSlice("experimental-disable-plugins"), - PluginsNoDefaults: cmd.Bool("experimental-no-default-plugins"), + PluginsEnabled: cmd.StringSlice(FallbackToDeprecatedName(cmd, "x-plugins", "experimental-plugins")), + PluginsDisabled: cmd.StringSlice(FallbackToDeprecatedName(cmd, "x-disable-plugins", "experimental-disable-plugins")), + PluginsNoDefaults: cmd.Bool(FallbackToDeprecatedName(cmd, "x-no-default-plugins", "experimental-no-default-plugins")), HTTPClient: client, - FlagDeprecatedPackages: cmd.Bool("experimental-flag-deprecated-packages"), + FlagDeprecatedPackages: cmd.Bool(FallbackToDeprecatedName(cmd, "x-flag-deprecated-packages", "experimental-flag-deprecated-packages")), } } diff --git a/cmd/osv-scanner/scan/image/command.go b/cmd/osv-scanner/scan/image/command.go index 9751a7f8be8..0f882fc1f0d 100644 --- a/cmd/osv-scanner/scan/image/command.go +++ b/cmd/osv-scanner/scan/image/command.go @@ -49,11 +49,7 @@ func action(_ context.Context, cmd *cli.Command, stdout, stderr io.Writer, clien } format := cmd.String("format") - outputPath := cmd.String("output-file") - - if outputPath == "" { - outputPath = cmd.String("output") - } + outputPath := cmd.String(helper.FallbackToDeprecatedName(cmd, "output-file", "output")) serve := cmd.Bool("serve") if serve { format = "html" diff --git a/cmd/osv-scanner/scan/image/command_test.go b/cmd/osv-scanner/scan/image/command_test.go index 63ce381cd89..3ca61e640ab 100644 --- a/cmd/osv-scanner/scan/image/command_test.go +++ b/cmd/osv-scanner/scan/image/command_test.go @@ -23,8 +23,8 @@ func TestCommand_ExplicitExtractors_WithDefaults(t *testing.T) { Args: []string{ "", "image", "--archive", - "--experimental-plugins=sbom/spdx", - "--experimental-plugins=sbom/cdx", + "--x-plugins=sbom/spdx", + "--x-plugins=sbom/cdx", "testdata/test-alpine-sbom.tar", }, Exit: 1, @@ -34,9 +34,9 @@ func TestCommand_ExplicitExtractors_WithDefaults(t *testing.T) { Args: []string{ "", "image", "--archive", - "--experimental-plugins=sbom/spdx", - "--experimental-plugins=sbom/cdx", - "--experimental-disable-plugins=sbom", + "--x-plugins=sbom/spdx", + "--x-plugins=sbom/cdx", + "--x-disable-plugins=sbom", "testdata/test-alpine-sbom.tar", }, Exit: 1, @@ -46,8 +46,8 @@ func TestCommand_ExplicitExtractors_WithDefaults(t *testing.T) { Args: []string{ "", "image", "--archive", - "--experimental-plugins=sbom", - "--experimental-disable-plugins=sbom", + "--x-plugins=sbom", + "--x-disable-plugins=sbom", "testdata/test-alpine-sbom.tar", }, Exit: 1, @@ -57,8 +57,8 @@ func TestCommand_ExplicitExtractors_WithDefaults(t *testing.T) { Args: []string{ "", "image", "--archive", - "--experimental-plugins=sbom/spdx,sbom/cdx", - "--experimental-disable-plugins=sbom", + "--x-plugins=sbom/spdx,sbom/cdx", + "--x-disable-plugins=sbom", "testdata/test-alpine-sbom.tar", }, Exit: 1, @@ -88,9 +88,9 @@ func TestCommand_ExplicitExtractors_WithoutDefaults(t *testing.T) { Args: []string{ "", "image", "--archive", - "--experimental-plugins=sbom/spdx", - "--experimental-plugins=sbom/cdx", - "--experimental-no-default-plugins", + "--x-plugins=sbom/spdx", + "--x-plugins=sbom/cdx", + "--x-no-default-plugins", "testdata/test-alpine-sbom.tar", }, Exit: 1, @@ -100,10 +100,10 @@ func TestCommand_ExplicitExtractors_WithoutDefaults(t *testing.T) { Args: []string{ "", "image", "--archive", - "--experimental-plugins=sbom/spdx", - "--experimental-plugins=sbom/cdx", - "--experimental-disable-plugins=sbom", - "--experimental-no-default-plugins", + "--x-plugins=sbom/spdx", + "--x-plugins=sbom/cdx", + "--x-disable-plugins=sbom", + "--x-no-default-plugins", "testdata/test-alpine-sbom.tar", }, Exit: 127, @@ -113,9 +113,9 @@ func TestCommand_ExplicitExtractors_WithoutDefaults(t *testing.T) { Args: []string{ "", "image", "--archive", - "--experimental-plugins=sbom", - "--experimental-disable-plugins=sbom", - "--experimental-no-default-plugins", + "--x-plugins=sbom", + "--x-disable-plugins=sbom", + "--x-no-default-plugins", "testdata/test-alpine-sbom.tar", }, Exit: 127, @@ -125,9 +125,9 @@ func TestCommand_ExplicitExtractors_WithoutDefaults(t *testing.T) { Args: []string{ "", "image", "--archive", - "--experimental-plugins=sbom/spdx,sbom/cdx", - "--experimental-disable-plugins=sbom", - "--experimental-no-default-plugins", + "--x-plugins=sbom/spdx,sbom/cdx", + "--x-disable-plugins=sbom", + "--x-no-default-plugins", "testdata/test-alpine-sbom.tar", }, Exit: 127, @@ -193,7 +193,7 @@ func TestCommand_Docker(t *testing.T) { // since we've requested the os/apk extractor disabled, and there's nothing else // in the image that we support extracting Name: "real_alpine_image_without_apk_extractor_enabled", - Args: []string{"", "image", "--experimental-disable-plugins=os/apk", "alpine:3.18.9"}, + Args: []string{"", "image", "--x-disable-plugins=os/apk", "alpine:3.18.9"}, Exit: 128, }, } @@ -325,8 +325,8 @@ func TestCommand_OCIImage(t *testing.T) { Name: "scanning_insecure_alpine_image_with_specific_detector_enabled", Args: []string{ "", "image", - "--experimental-plugins", "os/apk", - "--experimental-plugins", "weakcredentials/etcshadow", + "--x-plugins", "os/apk", + "--x-plugins", "weakcredentials/etcshadow", "--archive", "./testdata/test-alpine-etcshadow.tar", }, Exit: 1, @@ -335,9 +335,9 @@ func TestCommand_OCIImage(t *testing.T) { Name: "scanning_insecure_alpine_image_with_specific_detector_disabled", Args: []string{ "", "image", - "--experimental-plugins", "os/apk", - "--experimental-plugins", "weakcreds", - "--experimental-disable-plugins", "weakcredentials/etcshadow", + "--x-plugins", "os/apk", + "--x-plugins", "weakcreds", + "--x-disable-plugins", "weakcredentials/etcshadow", "--archive", "./testdata/test-alpine-etcshadow.tar", }, Exit: 1, @@ -346,8 +346,8 @@ func TestCommand_OCIImage(t *testing.T) { Name: "scanning_insecure_alpine_image_with_detector_preset", Args: []string{ "", "image", - "--experimental-plugins", "os/apk", - "--experimental-plugins", "weakcreds", + "--x-plugins", "os/apk", + "--x-plugins", "weakcreds", "--archive", "./testdata/test-alpine-etcshadow.tar", }, Exit: 1, @@ -445,8 +445,8 @@ func TestCommand_OCIImage_JSONFormat(t *testing.T) { Name: "scanning_insecure_alpine_image_with_specific_detector_enabled", Args: []string{ "", "image", "--format=json", - "--experimental-plugins", "os/apk", - "--experimental-plugins", "weakcredentials/etcshadow", + "--x-plugins", "os/apk", + "--x-plugins", "weakcredentials/etcshadow", "--archive", "./testdata/test-alpine-etcshadow.tar", }, Exit: 1, @@ -461,8 +461,8 @@ func TestCommand_OCIImage_JSONFormat(t *testing.T) { Name: "scanning_insecure_alpine_image_with_detector_preset", Args: []string{ "", "image", "--format=json", - "--experimental-plugins", "os/apk", - "--experimental-plugins", "weakcreds", + "--x-plugins", "os/apk", + "--x-plugins", "weakcreds", "--archive", "./testdata/test-alpine-etcshadow.tar", }, Exit: 1, @@ -477,7 +477,7 @@ func TestCommand_OCIImage_JSONFormat(t *testing.T) { Name: "scanning_image_with_deprecated_packages", Args: []string{ "", "image", "--format=json", - "--experimental-flag-deprecated-packages", + "--x-flag-deprecated-packages", "--archive", "./testdata/test-image-with-deprecated.tar", }, Exit: 1, diff --git a/cmd/osv-scanner/scan/source/__snapshots__/command_test.snap b/cmd/osv-scanner/scan/source/__snapshots__/command_test.snap index e3f4800db9f..89d77fb7f9e 100755 --- a/cmd/osv-scanner/scan/source/__snapshots__/command_test.snap +++ b/cmd/osv-scanner/scan/source/__snapshots__/command_test.snap @@ -758,6 +758,19 @@ No issues found --- +[TestCommand/exclude_with_exact_directory_name_using_deprecated_flag - 1] +Warning: --experimental-exclude has been deprecated in favor of --x-exclude +Scanning dir ./testdata/locks-one-with-nested +Scanned /testdata/locks-one-with-nested/nested/composer.lock file and found 1 package +Scanned /testdata/locks-one-with-nested/yarn.lock file and found 1 package +No issues found + +--- + +[TestCommand/exclude_with_exact_directory_name_using_deprecated_flag - 2] + +--- + [TestCommand/exclude_with_glob_pattern - 1] Scanning dir ./testdata/locks-one-with-nested Scanned /testdata/locks-one-with-nested/nested/composer.lock file and found 1 package @@ -1138,7 +1151,8 @@ OPTIONS: --recursive, -r check subdirectories --no-ignore also scan files that would be ignored by .gitignore --include-git-root include scanning git root (non-submoduled) repositories - --experimental-exclude string [ --experimental-exclude string ] exclude directory paths during scanning; use g:pattern for glob, r:pattern for regex, or just dirname for exact match (can be repeated) + --experimental-exclude string [ --experimental-exclude string ] [DEPRECATED] (use "--x-exclude" instead) exclude directory paths during scanning; use g:pattern for glob, r:pattern for regex, or just dirname for exact match (can be repeated) + --x-exclude string [ --x-exclude string ] exclude directory paths during scanning; use g:pattern for glob, r:pattern for regex, or just dirname for exact match (can be repeated) --data-source string source to fetch package information from; value can be: deps.dev, native (default: "deps.dev") --maven-registry string URL of the default registry to fetch Maven metadata --config string set/override config file @@ -1158,10 +1172,14 @@ OPTIONS: --all-packages when json output is selected, prints all packages --all-vulns show all vulnerabilities including unimportant and uncalled ones --licenses value report on licenses based on an allowlist - --experimental-flag-deprecated-packages report if package versions are deprecated - --experimental-plugins string [ --experimental-plugins string ] list of specific plugins and presets of plugins to use (default: "lockfile", "sbom", "directory") - --experimental-disable-plugins string [ --experimental-disable-plugins string ] list of specific plugins and presets of plugins to not use - --experimental-no-default-plugins disable default plugins, instead using only those enabled by --experimental-plugins + --x-flag-deprecated-packages report if package versions are deprecated + --experimental-flag-deprecated-packages [DEPRECATED] (use "--x-flag-deprecated-packages" instead) report if package versions are deprecated + --experimental-plugins string [ --experimental-plugins string ] [DEPRECATED] (use "--x-plugins" instead) list of specific plugins and presets of plugins to use (default: "lockfile", "sbom", "directory") + --x-plugins string [ --x-plugins string ] list of specific plugins and presets of plugins to use (default: "lockfile", "sbom", "directory") + --experimental-disable-plugins string [ --experimental-disable-plugins string ] [DEPRECATED] (use "--x-disable-plugins" instead) list of specific plugins and presets of plugins to not use + --x-disable-plugins string [ --x-disable-plugins string ] list of specific plugins and presets of plugins to not use + --experimental-no-default-plugins [DEPRECATED] (use "--x-no-default-plugins" instead) disable default plugins, instead using only those enabled by --x-plugins + --x-no-default-plugins disable default plugins, instead using only those enabled by --experimental-plugins --help, -h show help --- @@ -2469,17 +2487,39 @@ Total 22 packages affected by 164 known vulnerabilities (19 Critical, 67 High, 5 --- -[TestCommand_ExplicitExtractors_WithDefaults/empty_plugins_flag_does_nothing - 1] +[TestCommand_ExplicitExtractors_WithDefaults/deprecated_empty_plugins_flag_does_nothing - 1] --- -[TestCommand_ExplicitExtractors_WithDefaults/empty_plugins_flag_does_nothing - 2] +[TestCommand_ExplicitExtractors_WithDefaults/deprecated_empty_plugins_flag_does_nothing - 2] Incorrect Usage: flag needs an argument: --experimental-plugins= flag needs an argument: --experimental-plugins= --- +[TestCommand_ExplicitExtractors_WithDefaults/deprecated_extractors_cancelled_out_specified_individually - 1] +Warning: --experimental-plugins has been deprecated in favor of --x-plugins +Warning: --experimental-disable-plugins has been deprecated in favor of --x-disable-plugins + +--- + +[TestCommand_ExplicitExtractors_WithDefaults/deprecated_extractors_cancelled_out_specified_individually - 2] +No package sources found, --help for usage information. + +--- + +[TestCommand_ExplicitExtractors_WithDefaults/empty_plugins_flag_does_nothing - 1] + +--- + +[TestCommand_ExplicitExtractors_WithDefaults/empty_plugins_flag_does_nothing - 2] +Incorrect Usage: flag needs an argument: --x-plugins= + +flag needs an argument: --x-plugins= + +--- + [TestCommand_ExplicitExtractors_WithDefaults/extractors_cancelled_out_specified_individually - 1] --- @@ -2618,17 +2658,40 @@ could not determine extractor, requested package-lock.json --- -[TestCommand_ExplicitExtractors_WithoutDefaults/empty_plugins_flag_does_nothing - 1] +[TestCommand_ExplicitExtractors_WithoutDefaults/deprecated_empty_plugins_flag_does_nothing - 1] --- -[TestCommand_ExplicitExtractors_WithoutDefaults/empty_plugins_flag_does_nothing - 2] +[TestCommand_ExplicitExtractors_WithoutDefaults/deprecated_empty_plugins_flag_does_nothing - 2] Incorrect Usage: flag needs an argument: --experimental-plugins= flag needs an argument: --experimental-plugins= --- +[TestCommand_ExplicitExtractors_WithoutDefaults/deprecated_extractors_cancelled_out_specified_individually - 1] +Warning: --experimental-plugins has been deprecated in favor of --x-plugins +Warning: --experimental-disable-plugins has been deprecated in favor of --x-disable-plugins +Warning: --experimental-no-default-plugins has been deprecated in favor of --x-no-default-plugins + +--- + +[TestCommand_ExplicitExtractors_WithoutDefaults/deprecated_extractors_cancelled_out_specified_individually - 2] +at least one extractor must be enabled + +--- + +[TestCommand_ExplicitExtractors_WithoutDefaults/empty_plugins_flag_does_nothing - 1] + +--- + +[TestCommand_ExplicitExtractors_WithoutDefaults/empty_plugins_flag_does_nothing - 2] +Incorrect Usage: flag needs an argument: --x-plugins= + +flag needs an argument: --x-plugins= + +--- + [TestCommand_ExplicitExtractors_WithoutDefaults/extractors_cancelled_out_specified_individually - 1] --- @@ -2985,6 +3048,84 @@ Total 1 package deprecated. --- +[TestCommand_FlagDeprecatedPackages/package_deprecated_true_with_vuln_table_and_new_flag_false - 1] +Warning: --experimental-flag-deprecated-packages has been deprecated in favor of --x-flag-deprecated-packages +Scanning dir ./testdata/exp-plugins-pkgdeprecate/deprecated-vuln/Cargo.lock +Scanned /testdata/exp-plugins-pkgdeprecate/deprecated-vuln/Cargo.lock file and found 7 packages + +Total 1 package affected by 2 known vulnerabilities (0 Critical, 0 High, 1 Medium, 0 Low, 1 Unknown) from 1 ecosystem. +1 vulnerability can be fixed. + ++-------------------------------------+------+-----------+---------+---------+---------------+--------------------------------------------------------------+ +| OSV URL | CVSS | ECOSYSTEM | PACKAGE | VERSION | FIXED VERSION | SOURCE | ++-------------------------------------+------+-----------+---------+---------+---------------+--------------------------------------------------------------+ +| https://osv.dev/RUSTSEC-2020-0016 | | crates.io | net2 | 0.2.33 | -- | testdata/exp-plugins-pkgdeprecate/deprecated-vuln/Cargo.lock | +| https://osv.dev/RUSTSEC-2020-0078 | 5.5 | crates.io | net2 | 0.2.33 | 0.2.36 | testdata/exp-plugins-pkgdeprecate/deprecated-vuln/Cargo.lock | +| https://osv.dev/GHSA-458v-4hrf-g3m4 | | | | | | | +| https://osv.dev/GHSA-c79c-gwph-gqfm | | | | | | | ++-------------------------------------+------+-----------+---------+---------+---------------+--------------------------------------------------------------+ + +--- + +[TestCommand_FlagDeprecatedPackages/package_deprecated_true_with_vuln_table_and_new_flag_false - 2] + +--- + +[TestCommand_FlagDeprecatedPackages/package_deprecated_true_with_vuln_table_and_old_flag_false - 1] +Warning: --experimental-flag-deprecated-packages has been deprecated in favor of --x-flag-deprecated-packages +Scanning dir ./testdata/exp-plugins-pkgdeprecate/deprecated-vuln/Cargo.lock +Scanned /testdata/exp-plugins-pkgdeprecate/deprecated-vuln/Cargo.lock file and found 7 packages + +Total 1 package affected by 2 known vulnerabilities (0 Critical, 0 High, 1 Medium, 0 Low, 1 Unknown) from 1 ecosystem. +1 vulnerability can be fixed. + ++-------------------------------------+------+-----------+---------+---------+---------------+--------------------------------------------------------------+ +| OSV URL | CVSS | ECOSYSTEM | PACKAGE | VERSION | FIXED VERSION | SOURCE | ++-------------------------------------+------+-----------+---------+---------+---------------+--------------------------------------------------------------+ +| https://osv.dev/RUSTSEC-2020-0016 | | crates.io | net2 | 0.2.33 | -- | testdata/exp-plugins-pkgdeprecate/deprecated-vuln/Cargo.lock | +| https://osv.dev/RUSTSEC-2020-0078 | 5.5 | crates.io | net2 | 0.2.33 | 0.2.36 | testdata/exp-plugins-pkgdeprecate/deprecated-vuln/Cargo.lock | +| https://osv.dev/GHSA-458v-4hrf-g3m4 | | | | | | | +| https://osv.dev/GHSA-c79c-gwph-gqfm | | | | | | | ++-------------------------------------+------+-----------+---------+---------+---------------+--------------------------------------------------------------+ + +--- + +[TestCommand_FlagDeprecatedPackages/package_deprecated_true_with_vuln_table_and_old_flag_false - 2] + +--- + +[TestCommand_FlagDeprecatedPackages/package_deprecated_true_with_vuln_table_using_old_flag - 1] +Warning: --experimental-flag-deprecated-packages has been deprecated in favor of --x-flag-deprecated-packages +Scanning dir ./testdata/exp-plugins-pkgdeprecate/deprecated-vuln/Cargo.lock +Scanned /testdata/exp-plugins-pkgdeprecate/deprecated-vuln/Cargo.lock file and found 7 packages + +Total 1 package affected by 2 known vulnerabilities (0 Critical, 0 High, 1 Medium, 0 Low, 1 Unknown) from 1 ecosystem. +1 vulnerability can be fixed. + ++-------------------------------------+------+-----------+---------+---------+---------------+--------------------------------------------------------------+ +| OSV URL | CVSS | ECOSYSTEM | PACKAGE | VERSION | FIXED VERSION | SOURCE | ++-------------------------------------+------+-----------+---------+---------+---------------+--------------------------------------------------------------+ +| https://osv.dev/RUSTSEC-2020-0016 | | crates.io | net2 | 0.2.33 | -- | testdata/exp-plugins-pkgdeprecate/deprecated-vuln/Cargo.lock | +| https://osv.dev/RUSTSEC-2020-0078 | 5.5 | crates.io | net2 | 0.2.33 | 0.2.36 | testdata/exp-plugins-pkgdeprecate/deprecated-vuln/Cargo.lock | +| https://osv.dev/GHSA-458v-4hrf-g3m4 | | | | | | | +| https://osv.dev/GHSA-c79c-gwph-gqfm | | | | | | | ++-------------------------------------+------+-----------+---------+---------+---------------+--------------------------------------------------------------+ +Total 1 package deprecated. + ++----------------------------------------------------------------------------------------------+ +| Deprecated packages | ++-----------+---------+---------+--------------------------------------------------------------+ +| ECOSYSTEM | PACKAGE | VERSION | SOURCE | ++-----------+---------+---------+--------------------------------------------------------------+ +| crates.io | net2 | 0.2.33 | testdata/exp-plugins-pkgdeprecate/deprecated-vuln/Cargo.lock | ++-----------+---------+---------+--------------------------------------------------------------+ + +--- + +[TestCommand_FlagDeprecatedPackages/package_deprecated_true_with_vuln_table_using_old_flag - 2] + +--- + [TestCommand_GithubActions/scanning_osv-scanner_custom_format - 1] Scanned /testdata/locks-insecure/osv-scanner-flutter-deps.json file and found 3 packages diff --git a/cmd/osv-scanner/scan/source/command.go b/cmd/osv-scanner/scan/source/command.go index 06301571ae3..4c7d5b09e34 100644 --- a/cmd/osv-scanner/scan/source/command.go +++ b/cmd/osv-scanner/scan/source/command.go @@ -59,6 +59,15 @@ func Command(stdout, stderr io.Writer, client *http.Client) *cli.Command { }, &cli.StringSliceFlag{ Name: "experimental-exclude", + Usage: "[DEPRECATED] (use \"--x-exclude\" instead) exclude directory paths during scanning; use g:pattern for glob, r:pattern for regex, or just dirname for exact match (can be repeated)", + Action: func(_ context.Context, _ *cli.Command, _ []string) error { + cmdlogger.Warnf("Warning: --experimental-exclude has been deprecated in favor of --x-exclude") + + return nil + }, + }, + &cli.StringSliceFlag{ + Name: "x-exclude", Usage: "exclude directory paths during scanning; use g:pattern for glob, r:pattern for regex, or just dirname for exact match (can be repeated)", }, &cli.StringFlag{ @@ -88,11 +97,7 @@ func Command(stdout, stderr io.Writer, client *http.Client) *cli.Command { func action(_ context.Context, cmd *cli.Command, stdout, stderr io.Writer, client *http.Client) error { format := cmd.String("format") - outputPath := cmd.String("output-file") - - if outputPath == "" { - outputPath = cmd.String("output") - } + outputPath := cmd.String(helper.FallbackToDeprecatedName(cmd, "output-file", "output")) serve := cmd.Bool("serve") if serve { format = "html" @@ -117,7 +122,7 @@ func action(_ context.Context, cmd *cli.Command, stdout, stderr io.Writer, clien experimentalScannerActions := helper.GetExperimentalScannerActions(cmd, client) experimentalScannerActions.RequestUserAgent = "osv-scanner_scan-source/" + version.OSVVersion - experimentalScannerActions.ExcludePatterns = cmd.StringSlice("experimental-exclude") + experimentalScannerActions.ExcludePatterns = cmd.StringSlice(helper.FallbackToDeprecatedName(cmd, "x-exclude", "experimental-exclude")) // Add `source` specific experimental configs experimentalScannerActions.TransitiveScanning = osvscanner.TransitiveScanningActions{ Disabled: cmd.Bool("no-resolve"), diff --git a/cmd/osv-scanner/scan/source/command_test.go b/cmd/osv-scanner/scan/source/command_test.go index 3febffb55d7..712d80faeea 100644 --- a/cmd/osv-scanner/scan/source/command_test.go +++ b/cmd/osv-scanner/scan/source/command_test.go @@ -162,32 +162,37 @@ func TestCommand(t *testing.T) { // experimental exclude flag tests { Name: "exclude_with_exact_directory_name", + Args: []string{"", "source", "--recursive", "--x-exclude=nested", "./testdata/locks-one-with-nested"}, + Exit: 0, + }, + { + Name: "exclude_with_exact_directory_name_using_deprecated_flag", Args: []string{"", "source", "--recursive", "--experimental-exclude=nested", "./testdata/locks-one-with-nested"}, Exit: 0, }, { Name: "exclude_with_glob_pattern", - Args: []string{"", "source", "--recursive", "--experimental-exclude=g:**/nested/**", "./testdata/locks-one-with-nested"}, + Args: []string{"", "source", "--recursive", "--x-exclude=g:**/nested/**", "./testdata/locks-one-with-nested"}, Exit: 0, }, { Name: "exclude_with_regex_pattern", - Args: []string{"", "source", "--recursive", "--experimental-exclude=r:/nested$", "./testdata/locks-one-with-nested"}, + Args: []string{"", "source", "--recursive", "--x-exclude=r:/nested$", "./testdata/locks-one-with-nested"}, Exit: 0, }, { Name: "exclude_with_invalid_regex_returns_error", - Args: []string{"", "source", "--experimental-exclude=r:[invalid", "./testdata/locks-many"}, + Args: []string{"", "source", "--x-exclude=r:[invalid", "./testdata/locks-many"}, Exit: 127, }, { Name: "exclude_with_multiple_exact_directories", - Args: []string{"", "source", "--recursive", "--experimental-exclude=nested", "--experimental-exclude=other", "./testdata/locks-one-with-nested"}, + Args: []string{"", "source", "--recursive", "--x-exclude=nested", "--x-exclude=other", "./testdata/locks-one-with-nested"}, Exit: 0, }, { Name: "exclude_with_multiple_pattern_types", - Args: []string{"", "source", "--recursive", "--experimental-exclude=nested", "--experimental-exclude=g:**/vendor/**", "--experimental-exclude=r:\\.cache$", "./testdata/locks-one-with-nested"}, + Args: []string{"", "source", "--recursive", "--x-exclude=nested", "--x-exclude=g:**/vendor/**", "--x-exclude=r:\\.cache$", "./testdata/locks-one-with-nested"}, Exit: 0, }, { @@ -425,17 +430,17 @@ func TestCommand_JavareachArchive(t *testing.T) { tests := []testcmd.Case{ { Name: "jars_can_be_scanned_without_call_analysis", - Args: []string{"", "source", "--all-vulns", "--experimental-plugins=artifact", "./testdata/artifact/javareach_test.jar"}, + Args: []string{"", "source", "--all-vulns", "--x-plugins=artifact", "./testdata/artifact/javareach_test.jar"}, Exit: 1, }, { Name: "jars_can_be_scanned_with_call_analysis", - Args: []string{"", "source", "--call-analysis=jar", "--all-vulns", "--experimental-plugins=artifact", "./testdata/artifact/javareach_test.jar"}, + Args: []string{"", "source", "--call-analysis=jar", "--all-vulns", "--x-plugins=artifact", "./testdata/artifact/javareach_test.jar"}, Exit: 1, }, { Name: "jars_can_be_scanned_with_call_analysis_and_disabled_enricher", - Args: []string{"", "source", "--call-analysis=jar", "--experimental-disable-plugins=reachability/java", "--all-vulns", "--experimental-plugins=artifact", "./testdata/artifact/javareach_test.jar"}, + Args: []string{"", "source", "--call-analysis=jar", "--x-disable-plugins=reachability/java", "--all-vulns", "--x-plugins=artifact", "./testdata/artifact/javareach_test.jar"}, Exit: 1, }, } @@ -458,16 +463,16 @@ func TestCommand_ExplicitExtractors_WithDefaults(t *testing.T) { tests := []testcmd.Case{ { Name: "empty_plugins_flag_does_nothing", - Args: []string{"", "source", "--experimental-plugins="}, + Args: []string{"", "source", "--x-plugins="}, Exit: 127, }, { Name: "extractors_cancelled_out_specified_individually", Args: []string{ "", "source", - "--experimental-plugins=sbom/spdx", - "--experimental-plugins=sbom/cdx", - "--experimental-disable-plugins=sbom", + "--x-plugins=sbom/spdx", + "--x-plugins=sbom/cdx", + "--x-disable-plugins=sbom", }, Exit: 128, }, @@ -475,8 +480,8 @@ func TestCommand_ExplicitExtractors_WithDefaults(t *testing.T) { Name: "extractors_cancelled_out_specified_together", Args: []string{ "", "source", - "--experimental-plugins=sbom/spdx,sbom/cdx", - "--experimental-disable-plugins=sbom", + "--x-plugins=sbom/spdx,sbom/cdx", + "--x-disable-plugins=sbom", }, Exit: 128, }, @@ -484,8 +489,8 @@ func TestCommand_ExplicitExtractors_WithDefaults(t *testing.T) { Name: "extractors_cancelled_out_with_presets", Args: []string{ "", "source", - "--experimental-plugins=sbom", - "--experimental-disable-plugins=sbom", + "--x-plugins=sbom", + "--x-disable-plugins=sbom", }, Exit: 128, }, @@ -495,7 +500,7 @@ func TestCommand_ExplicitExtractors_WithDefaults(t *testing.T) { Name: "scanning_directory_with_one_specific_extractor_enabled_and_the_defaults", Args: []string{ "", "source", - "--experimental-plugins=javascript/packagelockjson", + "--x-plugins=javascript/packagelockjson", "./testdata/locks-many", }, Exit: 0, @@ -504,9 +509,9 @@ func TestCommand_ExplicitExtractors_WithDefaults(t *testing.T) { Name: "scanning_directory_with_an_extractor_that_does_not_exist", Args: []string{ "", "source", - "--experimental-plugins=javascript/packagelockjson", - "--experimental-plugins=custom/extractor", - "--experimental-disable-plugins=custom/anotherextractor", + "--x-plugins=javascript/packagelockjson", + "--x-plugins=custom/extractor", + "--x-disable-plugins=custom/anotherextractor", "./testdata/locks-many", }, Exit: 127, @@ -517,8 +522,8 @@ func TestCommand_ExplicitExtractors_WithDefaults(t *testing.T) { Name: "scanning_directory_with_a_couple_of_specific_extractors_enabled_individually", Args: []string{ "", "source", - "--experimental-plugins=javascript/packagelockjson", - "--experimental-plugins=php/composerlock", + "--x-plugins=javascript/packagelockjson", + "--x-plugins=php/composerlock", "./testdata/locks-many", }, Exit: 0, @@ -529,7 +534,7 @@ func TestCommand_ExplicitExtractors_WithDefaults(t *testing.T) { Name: "scanning_directory_with_a_couple_of_specific_extractors_enabled_specified_together", Args: []string{ "", "source", - "--experimental-plugins=javascript/packagelockjson,php/composerlock", + "--x-plugins=javascript/packagelockjson,php/composerlock", "./testdata/locks-many", }, Exit: 0, @@ -540,7 +545,7 @@ func TestCommand_ExplicitExtractors_WithDefaults(t *testing.T) { Name: "scanning_directory_with_one_specific_extractor_disabled", Args: []string{ "", "source", - "--experimental-disable-plugins=javascript/packagelockjson", + "--x-disable-plugins=javascript/packagelockjson", "./testdata/locks-many", }, Exit: 0, @@ -550,7 +555,7 @@ func TestCommand_ExplicitExtractors_WithDefaults(t *testing.T) { Name: "scanning_file_with_one_specific_extractor_enabled", Args: []string{ "", "source", - "--experimental-plugins=javascript/packagelockjson", + "--x-plugins=javascript/packagelockjson", "./testdata/locks-many/package-lock.json", }, Exit: 0, @@ -560,7 +565,7 @@ func TestCommand_ExplicitExtractors_WithDefaults(t *testing.T) { Name: "scanning_file_with_one_different_extractor_enabled", Args: []string{ "", "source", - "--experimental-plugins=javascript/packagelockjson", + "--x-plugins=javascript/packagelockjson", "./testdata/locks-many/composer.lock", }, Exit: 0, @@ -572,11 +577,27 @@ func TestCommand_ExplicitExtractors_WithDefaults(t *testing.T) { Name: "scanning_file_with_parse_as_but_specific_extractor_disabled", Args: []string{ "", "source", - "--experimental-disable-plugins=javascript/packagelockjson", + "--x-disable-plugins=javascript/packagelockjson", "-L", "package-lock.json:./testdata/locks-many/composer.lock", }, Exit: 127, }, + // when using deprecated versions of the flags + { + Name: "deprecated_empty_plugins_flag_does_nothing", + Args: []string{"", "source", "--experimental-plugins="}, + Exit: 127, + }, + { + Name: "deprecated_extractors_cancelled_out_specified_individually", + Args: []string{ + "", "source", + "--experimental-plugins=sbom/spdx", + "--x-plugins=sbom/cdx", + "--experimental-disable-plugins=sbom", + }, + Exit: 128, + }, } for _, tt := range tests { t.Run(tt.Name, func(t *testing.T) { @@ -597,17 +618,17 @@ func TestCommand_ExplicitExtractors_WithoutDefaults(t *testing.T) { tests := []testcmd.Case{ { Name: "empty_plugins_flag_does_nothing", - Args: []string{"", "source", "--experimental-no-default-plugins", "--experimental-plugins="}, + Args: []string{"", "source", "--x-no-default-plugins", "--x-plugins="}, Exit: 127, }, { Name: "extractors_cancelled_out_specified_individually", Args: []string{ "", "source", - "--experimental-plugins=sbom/spdx", - "--experimental-plugins=sbom/cdx", - "--experimental-disable-plugins=sbom", - "--experimental-no-default-plugins", + "--x-plugins=sbom/spdx", + "--x-plugins=sbom/cdx", + "--x-disable-plugins=sbom", + "--x-no-default-plugins", }, Exit: 127, }, @@ -615,9 +636,9 @@ func TestCommand_ExplicitExtractors_WithoutDefaults(t *testing.T) { Name: "extractors_cancelled_out_specified_together", Args: []string{ "", "source", - "--experimental-plugins=sbom/spdx,sbom/cdx", - "--experimental-disable-plugins=sbom", - "--experimental-no-default-plugins", + "--x-plugins=sbom/spdx,sbom/cdx", + "--x-disable-plugins=sbom", + "--x-no-default-plugins", }, Exit: 127, }, @@ -625,9 +646,9 @@ func TestCommand_ExplicitExtractors_WithoutDefaults(t *testing.T) { Name: "extractors_cancelled_out_with_presets", Args: []string{ "", "source", - "--experimental-plugins=sbom", - "--experimental-disable-plugins=sbom", - "--experimental-no-default-plugins", + "--x-plugins=sbom", + "--x-disable-plugins=sbom", + "--x-no-default-plugins", }, Exit: 127, }, @@ -637,8 +658,8 @@ func TestCommand_ExplicitExtractors_WithoutDefaults(t *testing.T) { Name: "scanning_directory_with_one_specific_extractor_enabled_and_no_defaults", Args: []string{ "", "source", - "--experimental-plugins=javascript/packagelockjson", - "--experimental-no-default-plugins", + "--x-plugins=javascript/packagelockjson", + "--x-no-default-plugins", "./testdata/locks-many", }, Exit: 0, @@ -647,10 +668,10 @@ func TestCommand_ExplicitExtractors_WithoutDefaults(t *testing.T) { Name: "scanning_directory_with_an_extractor_that_does_not_exist", Args: []string{ "", "source", - "--experimental-plugins=javascript/packagelockjson", - "--experimental-plugins=custom/extractor", - "--experimental-disable-plugins=custom/anotherextractor", - "--experimental-no-default-plugins", + "--x-plugins=javascript/packagelockjson", + "--x-plugins=custom/extractor", + "--x-disable-plugins=custom/anotherextractor", + "--x-no-default-plugins", "./testdata/locks-many", }, Exit: 127, @@ -661,9 +682,9 @@ func TestCommand_ExplicitExtractors_WithoutDefaults(t *testing.T) { Name: "scanning_directory_with_a_couple_of_specific_extractors_enabled_individually", Args: []string{ "", "source", - "--experimental-plugins=javascript/packagelockjson", - "--experimental-plugins=php/composerlock", - "--experimental-no-default-plugins", + "--x-plugins=javascript/packagelockjson", + "--x-plugins=php/composerlock", + "--x-no-default-plugins", "./testdata/locks-many", }, Exit: 0, @@ -674,8 +695,8 @@ func TestCommand_ExplicitExtractors_WithoutDefaults(t *testing.T) { Name: "scanning_directory_with_a_couple_of_specific_extractors_enabled_specified_together", Args: []string{ "", "source", - "--experimental-plugins=javascript/packagelockjson,php/composerlock", - "--experimental-no-default-plugins", + "--x-plugins=javascript/packagelockjson,php/composerlock", + "--x-no-default-plugins", "./testdata/locks-many", }, Exit: 0, @@ -686,8 +707,8 @@ func TestCommand_ExplicitExtractors_WithoutDefaults(t *testing.T) { Name: "scanning_directory_with_one_specific_extractor_disabled", Args: []string{ "", "source", - "--experimental-disable-plugins=javascript/packagelockjson", - "--experimental-no-default-plugins", + "--x-disable-plugins=javascript/packagelockjson", + "--x-no-default-plugins", "./testdata/locks-many", }, Exit: 0, @@ -698,8 +719,8 @@ func TestCommand_ExplicitExtractors_WithoutDefaults(t *testing.T) { Name: "scanning_file_with_one_specific_extractor_enabled", Args: []string{ "", "source", - "--experimental-plugins=javascript/packagelockjson", - "--experimental-no-default-plugins", + "--x-plugins=javascript/packagelockjson", + "--x-no-default-plugins", "./testdata/locks-many/package-lock.json", }, Exit: 0, @@ -710,8 +731,8 @@ func TestCommand_ExplicitExtractors_WithoutDefaults(t *testing.T) { Name: "scanning_file_with_one_different_extractor_enabled", Args: []string{ "", "source", - "--experimental-plugins=javascript/packagelockjson", - "--experimental-no-default-plugins", + "--x-plugins=javascript/packagelockjson", + "--x-no-default-plugins", "./testdata/locks-many/composer.lock", }, Exit: 128, @@ -723,12 +744,29 @@ func TestCommand_ExplicitExtractors_WithoutDefaults(t *testing.T) { Name: "scanning_file_with_parse_as_but_specific_extractor_disabled", Args: []string{ "", "source", - "--experimental-disable-plugins=javascript/packagelockjson", - "--experimental-no-default-plugins", + "--x-disable-plugins=javascript/packagelockjson", + "--x-no-default-plugins", "-L", "package-lock.json:./testdata/locks-many/composer.lock", }, Exit: 127, }, + // when using deprecated versions of the flags + { + Name: "deprecated_empty_plugins_flag_does_nothing", + Args: []string{"", "source", "--experimental-no-default-plugins", "--experimental-plugins="}, + Exit: 127, + }, + { + Name: "deprecated_extractors_cancelled_out_specified_individually", + Args: []string{ + "", "source", + "--experimental-plugins=sbom/spdx", + "--x-plugins=sbom/cdx", + "--experimental-disable-plugins=sbom", + "--experimental-no-default-plugins", + }, + Exit: 127, + }, } for _, tt := range tests { t.Run(tt.Name, func(t *testing.T) { @@ -1307,7 +1345,7 @@ func TestCommand_Transitive(t *testing.T) { }, { Name: "pom.xml_enricher_requires_extractor", - Args: []string{"", "source", "--experimental-disable-plugins=java/pomxml", "./testdata/maven-transitive/abc.xml"}, + Args: []string{"", "source", "--x-disable-plugins=java/pomxml", "./testdata/maven-transitive/abc.xml"}, Exit: 128, }, { @@ -1337,7 +1375,7 @@ func TestCommand_Transitive(t *testing.T) { }, { Name: "requirements.txt_enricher_requires_extractor", - Args: []string{"", "source", "--experimental-disable-plugins=python/requirements", "./testdata/locks-requirements/requirements-transitive.txt"}, + Args: []string{"", "source", "--x-disable-plugins=python/requirements", "./testdata/locks-requirements/requirements-transitive.txt"}, Exit: 128, }, { @@ -1522,8 +1560,8 @@ func TestCommand_WithDetector_OnLinux(t *testing.T) { Name: "ssh_version_is_before_first_vuln_version", Args: []string{ "", "source", - "--experimental-plugins", "php/composerlock", - "--experimental-plugins", "cve/cve-2023-38408", + "--x-plugins", "php/composerlock", + "--x-plugins", "cve/cve-2023-38408", filepath.Join(testDir, "composer.lock"), }, Exit: 0, @@ -1533,8 +1571,8 @@ func TestCommand_WithDetector_OnLinux(t *testing.T) { Name: "ssh_version_is_after_last_vuln_version", Args: []string{ "", "source", - "--experimental-plugins", "php/composerlock", - "--experimental-plugins", "cve/cve-2023-38408", + "--x-plugins", "php/composerlock", + "--x-plugins", "cve/cve-2023-38408", filepath.Join(testDir, "composer.lock"), }, Exit: 0, @@ -1544,8 +1582,8 @@ func TestCommand_WithDetector_OnLinux(t *testing.T) { Name: "ssh_version_errors", Args: []string{ "", "source", - "--experimental-plugins", "php/composerlock", - "--experimental-plugins", "cve/cve-2023-38408", + "--x-plugins", "php/composerlock", + "--x-plugins", "cve/cve-2023-38408", filepath.Join(testDir, "composer.lock"), }, Exit: 0, @@ -1598,8 +1636,8 @@ func TestCommand_WithDetector_OffLinux(t *testing.T) { Name: "ssh_version_is_before_first_vuln_version", Args: []string{ "", "source", - "--experimental-plugins", "php/composerlock", - "--experimental-plugins", "cve/cve-2023-38408", + "--x-plugins", "php/composerlock", + "--x-plugins", "cve/cve-2023-38408", filepath.Join(testDir, "composer.lock"), }, Exit: 0, @@ -1609,8 +1647,8 @@ func TestCommand_WithDetector_OffLinux(t *testing.T) { Name: "ssh_version_is_after_last_vuln_version", Args: []string{ "", "source", - "--experimental-plugins", "php/composerlock", - "--experimental-plugins", "cve/cve-2023-38408", + "--x-plugins", "php/composerlock", + "--x-plugins", "cve/cve-2023-38408", filepath.Join(testDir, "composer.lock"), }, Exit: 0, @@ -1620,8 +1658,8 @@ func TestCommand_WithDetector_OffLinux(t *testing.T) { Name: "ssh_version_errors", Args: []string{ "", "source", - "--experimental-plugins", "php/composerlock", - "--experimental-plugins", "cve/cve-2023-38408", + "--x-plugins", "php/composerlock", + "--x-plugins", "cve/cve-2023-38408", filepath.Join(testDir, "composer.lock"), }, Exit: 0, @@ -1673,7 +1711,7 @@ func TestCommand_FlagDeprecatedPackages(t *testing.T) { Name: "package_deprecated_false_no_vuln_json", Args: []string{ "", "source", "--format=json", - "--experimental-flag-deprecated-packages", + "--x-flag-deprecated-packages", "./testdata/exp-plugins-pkgdeprecate/clean/Cargo.lock", }, Exit: 0, @@ -1682,7 +1720,7 @@ func TestCommand_FlagDeprecatedPackages(t *testing.T) { Name: "package_deprecated_true_no_vuln_json", Args: []string{ "", "source", "--format=json", - "--experimental-flag-deprecated-packages", + "--x-flag-deprecated-packages", "./testdata/exp-plugins-pkgdeprecate/deprecated-novuln/Cargo.lock", }, Exit: 1, @@ -1695,7 +1733,7 @@ func TestCommand_FlagDeprecatedPackages(t *testing.T) { Name: "package_deprecated_true_with_vuln_json", Args: []string{ "", "source", "--format=json", - "--experimental-flag-deprecated-packages", + "--x-flag-deprecated-packages", "./testdata/exp-plugins-pkgdeprecate/deprecated-vuln/Cargo.lock", }, Exit: 1, @@ -1708,7 +1746,7 @@ func TestCommand_FlagDeprecatedPackages(t *testing.T) { Name: "package_deprecated_npm_json", Args: []string{ "", "source", "--format=json", - "--experimental-flag-deprecated-packages", + "--x-flag-deprecated-packages", "./testdata/exp-plugins-pkgdeprecate/deprecated-npm/package-lock.json", }, Exit: 1, @@ -1721,7 +1759,7 @@ func TestCommand_FlagDeprecatedPackages(t *testing.T) { Name: "package_deprecated_true_no_vuln_table", Args: []string{ "", "source", "--format=table", - "--experimental-flag-deprecated-packages", + "--x-flag-deprecated-packages", "./testdata/exp-plugins-pkgdeprecate/deprecated-novuln/Cargo.lock", }, Exit: 1, @@ -1730,6 +1768,36 @@ func TestCommand_FlagDeprecatedPackages(t *testing.T) { Name: "package_deprecated_true_with_vuln_table", Args: []string{ "", "source", "--format=table", + "--x-flag-deprecated-packages", + "./testdata/exp-plugins-pkgdeprecate/deprecated-vuln/Cargo.lock", + }, + Exit: 1, + }, + // covers both the deprecated flag, and the general logic for deprecated (bool) flags + { + Name: "package_deprecated_true_with_vuln_table_using_old_flag", + Args: []string{ + "", "source", "--format=table", + "--experimental-flag-deprecated-packages", + "./testdata/exp-plugins-pkgdeprecate/deprecated-vuln/Cargo.lock", + }, + Exit: 1, + }, + { + Name: "package_deprecated_true_with_vuln_table_and_new_flag_false", + Args: []string{ + "", "source", "--format=table", + "--x-flag-deprecated-packages=false", + "--experimental-flag-deprecated-packages", + "./testdata/exp-plugins-pkgdeprecate/deprecated-vuln/Cargo.lock", + }, + Exit: 1, + }, + { + Name: "package_deprecated_true_with_vuln_table_and_old_flag_false", + Args: []string{ + "", "source", "--format=table", + "--x-flag-deprecated-packages=false", "--experimental-flag-deprecated-packages", "./testdata/exp-plugins-pkgdeprecate/deprecated-vuln/Cargo.lock", }, diff --git a/cmd/osv-scanner/scan/source/testdata/cassettes/TestCommand.yaml b/cmd/osv-scanner/scan/source/testdata/cassettes/TestCommand.yaml index a762d7b8294..548a5a55191 100644 --- a/cmd/osv-scanner/scan/source/testdata/cassettes/TestCommand.yaml +++ b/cmd/osv-scanner/scan/source/testdata/cassettes/TestCommand.yaml @@ -1998,6 +1998,58 @@ interactions: status: 200 OK code: 200 duration: 0s + - request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 278 + host: api.osv.dev + body: | + { + "queries": [ + { + "package": { + "ecosystem": "Packagist", + "name": "sentry/sdk" + }, + "version": "2.0.4" + }, + { + "package": { + "ecosystem": "npm", + "name": "balanced-match" + }, + "version": "1.0.2" + } + ] + } + headers: + Content-Type: + - application/json + X-Test-Name: + - TestCommand/exclude_with_exact_directory_name_using_deprecated_flag + url: https://api.osv.dev/v1/querybatch + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 19 + body: | + { + "results": [ + {}, + {} + ] + } + headers: + Content-Length: + - "19" + Content-Type: + - application/json + status: 200 OK + code: 200 + duration: 0s - request: proto: HTTP/1.1 proto_major: 1 diff --git a/docs/experimental.md b/docs/experimental.md index 34b6952b79f..8ed5ad339a9 100644 --- a/docs/experimental.md +++ b/docs/experimental.md @@ -12,4 +12,4 @@ has_children: true These features are currently under development. While their functionality may be subject to change, they are available for you to try. {: .note } -Features and flags with the `experimental` prefix might change or be removed with only a minor version update. +Features and flags with the `x` prefix are experimental and might change or be removed with only a minor version update. diff --git a/docs/installation.md b/docs/installation.md index d618dbc14d9..08b8a41f7fc 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -104,4 +104,5 @@ slsa-verifier verify-artifact ./osv-scanner_1.2.0_linux_amd64 --provenance-path ## SemVer Adherence All releases on the same Major version will be guaranteed to have backward compatible JSON output and CLI arguments. -However, features prefixed with `experimental` (e.g. `--experimental-call-analysis`) might be changed or removed with only a Minor version change. +However, features prefixed with `x` (e.g. `--x-call-analysis`) are experimental and might be changed or removed with +only a Minor version change. diff --git a/docs/manual-plugin-selection.md b/docs/manual-plugin-selection.md index 8e3de4b63b2..00d967d1326 100644 --- a/docs/manual-plugin-selection.md +++ b/docs/manual-plugin-selection.md @@ -30,9 +30,9 @@ you can manually enable or disable them. You can control which plugins to run using the following flags: -- `--experimental-plugins`: Enables a comma-separated list of specific plugins that will be used along with the default plugins for the command being run -- `--experimental-disable-plugins`: Disables a comma-separated list of specific plugins. -- `--experimental-no-default-plugins`: Excludes the default plugins for the command being run from being automatically included +- `--x-plugins`: Enables a comma-separated list of specific plugins that will be used along with the default plugins for the command being run +- `--x-disable-plugins`: Disables a comma-separated list of specific plugins. +- `--x-no-default-plugins`: Excludes the default plugins for the command being run from being automatically included For a full list of available plugin names, see OSV-Scalibr's documentation here: https://github.com/google/osv-scalibr/blob/main/docs/supported_inventory_types.md @@ -45,10 +45,10 @@ You can also enable or disable various presets, which group multiple plugins tog ```bash # This will enable all sbom plugins + cargolock extractor + requirements extractor -osv-scanner scan source --experimental-plugins sbom,rust/cargolock,python/requirements +osv-scanner scan source --x-plugins sbom,rust/cargolock,python/requirements # This will enable all lockfile plugins, except the cargolock and requirements extractors -osv-scanner scan source --experimental-plugins lockfile --experimental-disable-plugins rust/cargolock,python/requirements +osv-scanner scan source --x-plugins lockfile --x-disable-plugins rust/cargolock,python/requirements ``` **Available Presets:** @@ -81,7 +81,7 @@ Example detector run ```bash -osv-scanner scan image --experimental-plugins=os/apk,weakcredentials/etcshadow --format=json +osv-scanner scan image --x-plugins=os/apk,weakcredentials/etcshadow --format=json ``` ```json diff --git a/docs/migrating-from-scalibr.md b/docs/migrating-from-scalibr.md index b41bdb197fc..d0741ca8044 100644 --- a/docs/migrating-from-scalibr.md +++ b/docs/migrating-from-scalibr.md @@ -49,18 +49,18 @@ https://github.com/google/osv-scalibr/blob/main/docs/supported_inventory_types.m scalibr --plugins python/pip,go/gomod --detectors go/govulncheck /path/to/your/project ``` -In `osv-scanner`, you can achieve the same by using the `--experimental-plugins` flag. This is an experimental feature. +In `osv-scanner`, you can achieve the same by using the `--x-plugins` flag. This is an experimental feature. **osv-scanner:** ```sh -osv-scanner --experimental-plugins python/pip,go/gomod,go/govulncheck /path/to/your/project +osv-scanner --x-plugins python/pip,go/gomod,go/govulncheck /path/to/your/project ``` -`osv-scanner` lets you exclude its default plugins with `--experimental-no-default-plugins`, for when you want to only +`osv-scanner` lets you exclude its default plugins with `--x-no-default-plugins`, for when you want to only run specific plugins. -`osv-scanner` also allows you to disable specific plugins with `--experimental-disable-plugins`. +`osv-scanner` also allows you to disable specific plugins with `--x-disable-plugins`. For more details on manual plugin selection in `osv-scanner`, see the [manual plugin selection documentation](manual-plugin-selection.md). @@ -93,10 +93,10 @@ For more details on `osv-scanner` output formats, see the [output documentation] | `--root` | `[directory]` (argument) | `osv-scanner scan source [directory]` | | `--result` | `--output` | `osv-scanner --output ` | | `-o` | `--format` and `--output` | e.g. `osv-scalibr -o spdx23-json=r.json` becomes `osv-scanner --format spdx-2.3-json --output-file r.json` | -| `--plugins` | `--experimental-plugins` | | -| `--extractors` | `--experimental-plugins` | | -| `--detectors` | `--experimental-plugins` | | -| `--annotators` | `--experimental-plugins` | | +| `--plugins` | `--x-plugins` | | +| `--extractors` | `--x-plugins` | | +| `--detectors` | `--x-plugins` | | +| `--annotators` | `--x-plugins` | | | `--ignore-sub-dirs` | (no direct equivalent) | `osv-scanner` is not recursive by default. Use `--recursive` to enable. | | `--skip-dirs` | Not yet available | | | `--skip-dir-regex` | Not yet available | | diff --git a/docs/package-deprecation.md b/docs/package-deprecation.md index 61c95c4af92..2b1b83f141e 100644 --- a/docs/package-deprecation.md +++ b/docs/package-deprecation.md @@ -23,12 +23,12 @@ The `deprecated` field is a boolean value indicating if a package is flagged as ## Usage -To enable package deprecation reporting, use the `--experimental-flag-deprecated-packages` flag. The feature is not available in the `spdx` format. +To enable package deprecation reporting, use the `--x-flag-deprecated-packages` flag. The feature is not available in the `spdx` format. ### Project Source Scanning ```bash -osv-scanner scan source --experimental-flag-deprecated-packages -r /path/to/project +osv-scanner scan source --x-flag-deprecated-packages -r /path/to/project ``` For more details on source scanning, see [Project Source Scanning](./scan-source.md). @@ -37,10 +37,10 @@ For more details on source scanning, see [Project Source Scanning](./scan-source ```bash # Scan a local or remote image by name -osv-scanner scan image --experimental-flag-deprecated-packages my-image:tag +osv-scanner scan image --x-flag-deprecated-packages my-image:tag # Scan an exported image archive -osv-scanner scan image --experimental-flag-deprecated-packages --archive ./path/to/my-image.tar +osv-scanner scan image --x-flag-deprecated-packages --archive ./path/to/my-image.tar ``` For more details on image scanning, see [Container Image Scanning](./scan-image.md). diff --git a/docs/scan-source.md b/docs/scan-source.md index d384d07a4e1..21e20ddeca0 100644 --- a/docs/scan-source.md +++ b/docs/scan-source.md @@ -42,7 +42,7 @@ The `--no-ignore` flag can be used to force the scanner to scan ignored files. Experimental {: .label } -You can exclude specific paths from scanning using the `--experimental-exclude` flag. This is useful for excluding test directories, documentation, or vendor directories from vulnerability scans. +You can exclude specific paths from scanning using the `--x-exclude` flag. This is useful for excluding test directories, documentation, or vendor directories from vulnerability scans. **Note:** This flag currently only excludes directories, not individual files. This is an experimental feature and the syntax may change in future versions. @@ -58,26 +58,26 @@ The flag supports three pattern types, matching the `--lockfile` flag syntax: ```bash # Exclude directories named "test" or "docs" (exact match) -osv-scanner scan source -r --experimental-exclude=test --experimental-exclude=docs /path/to/your/dir +osv-scanner scan source -r --x-exclude=test --x-exclude=docs /path/to/your/dir # Exclude using glob patterns -osv-scanner scan source -r --experimental-exclude="g:**/test/**" --experimental-exclude="g:**/docs/**" /path/to/your/dir +osv-scanner scan source -r --x-exclude="g:**/test/**" --x-exclude="g:**/docs/**" /path/to/your/dir # Exclude using regex patterns -osv-scanner scan source -r --experimental-exclude="r:.*_test$" /path/to/your/dir +osv-scanner scan source -r --x-exclude="r:.*_test$" /path/to/your/dir # Mix different pattern types -osv-scanner scan source -r --experimental-exclude=vendor --experimental-exclude="g:**/test/**" --experimental-exclude="r:\\.cache" /path/to/your/dir +osv-scanner scan source -r --x-exclude=vendor --x-exclude="g:**/test/**" --x-exclude="r:\\.cache" /path/to/your/dir # Escape directory names containing colons using : prefix -osv-scanner scan source -r --experimental-exclude=":my:project" /path/to/your/dir +osv-scanner scan source -r --x-exclude=":my:project" /path/to/your/dir ``` ### Common use cases -- Excluding test directories: `--experimental-exclude=test` or `--experimental-exclude="g:**/test/**"` -- Excluding documentation: `--experimental-exclude=docs` -- Excluding vendor directories: `--experimental-exclude=vendor` +- Excluding test directories: `--x-exclude=test` or `--x-exclude="g:**/test/**"` +- Excluding documentation: `--x-exclude=docs` +- Excluding vendor directories: `--x-exclude=vendor` Alternatively, you can use the `osv-scanner.toml` configuration file with `[[PackageOverrides]]` to ignore specific packages or directories. See [Configuration](./configuration.md) for more details.