# Package Vulnerability Support in DotNet CLI

* Status: **Reviewing**
* Authors: [Xavier Decoster](https://github.com/xavierdecoster), [Drew Gillies](https://github.com/drewgillies)

## Issue

[8716](https://github.com/nuget/home/issues/8716) - Support Package Vulnerability feature in clients (phase 1)

## Problem Background

Developers take dependency on a set of packages directly or indirectly (through transitive dependencies) and have no way to understand if any of their dependencies bring in any known vulnerabilities.

NuGet should be able to flag vulnerable packages used in projects/solutions. To support this capability from the command line, a new `dotnet.exe` CLI option will be introduced.

This CLI command provides a way to verify *already installed* (direct and indirect) dependencies against known vulnerabilities.

## Who are the customers

All .NET Core customers.

## Requirements

It must be possible to combine the `--vulnerable` command option with the following flags:

* `--include-transitive`
* `--source`
* `--config`
* `--framework`
* `--interactive`
* `--help`

Combining the `--vulnerable` command option with the following flags will not be supported at this time:

* `--outdated`
* `--deprecated`

The following flags will are only relevant to the `--outdated` command option. They will continue to be ignored, without erroring, when using the `--deprecated` option, which is existing behavior. They will now also be ignored without erroring when using the `--vulnerable` option:

* `--include-prerelease`
* `--highest-minor`
* `--highest-patch`

An informational message will be printed when the ignored command options are used:

```shell
The command option(s) '--include-prerelease', '--highest-minor', and '--highest-patch' are ignored by this command.
```

## Solution

We'll introduce a new `--vulnerable` command option to the existing `dotnet list package` command.
This command option will offer a detailed view of already installed packages with known vulnerabilities.

The default behavior for `dotnet list package` will be unchanged.

### DotNet CLI

The `dotnet` CLI repository must be updated to:

* forward the `--vulnerable` command option for the `dotnet list package` command,
* handle the invalid combinations of command options, such as `--vulnerable --outdated`, `--vulnerable --deprecated`, and `--outdated --deprecated` (this last case is existing behavior).

### NuGet xplat CLI

The `nuget` xplat CLI code must be updated to:

* handle the `--vulnerable` command option for the `dotnet list package` command,
* handle the invalid combinations of command options, such as `--vulnerable --outdated`, `--vulnerable --deprecated`, and `--outdated --deprecated` (this last case is existing behavior).

### Command Output

#### Help

The `--help` output must be updated to include the new `--vulnerable` option. Other existing options should refer to the `--vulnerable` option as needed.

```shell
Usage: dotnet list <PROJECT | SOLUTION> package [options]

Arguments:
  <PROJECT | SOLUTION>   The project or solution file to operate on. If a file is not specified, the command will search the current directory for one.

Options:
  -h, --help                                Show command line help.
  --outdated                                Lists packages that have newer versions. Cannot be combined with `--deprecated` or `--vulnerable` options.
  --deprecated                              Lists packages that are deprecated. Cannot be combined with `--outdated` or `--vulnerable` options.
  --vulnerable                              Lists packages that have known vulnerabilities. Cannot be combined with `--outdated` or `--deprecated` options.
  --framework <FRAMEWORK | FRAMEWORK\RID>   Chooses a framework to show its packages. Use the option multiple times for multiple frameworks.
  --include-transitive                      Lists transitive and top-level packages.
  --include-prerelease                      Consider packages with prerelease versions when searching for newer packages. Requires the '--outdated' option.
  --highest-patch                           Consider only the packages with a matching major and minor version numbers when searching for newer packages. Requires the '--outdated' option.
  --highest-minor                           Consider only the packages with a matching major version number when searching for newer packages. Requires the '--outdated' option.
  --config <CONFIG_FILE>                    The path to the NuGet config file to use. Requires the '--outdated', '--deprecated', or `--vulnerable` option.
  --source <SOURCE>                         The NuGet sources to use when searching for newer packages. Requires the '--outdated', '--deprecated', or `--vulnerable` option.
```

#### List

The default behavior for `dotnet list package` will be unchanged.

```shell
dotnet list package
```

Lists the package references for a project or solution.

```shell
> dotnet list package

Project 'MySampleProject' has the following package references
   [netcoreapp2.1]:
   Top-level Package               Requested   Resolved
   > Microsoft.ML                  0.11.0      0.11.0
   > Microsoft.NETCore.App   (A)   [2.1.0, )   2.1.0
   > My.Outdated.Package           0.1.0       0.1.0
   > My.Deprecated.Package         1.0.0       1.0.0
   > My.Vulnerable.Package         1.0.1       1.0.1

(A): Auto-referenced package(s).
```

#### Outdated

```shell
dotnet list package --outdated
```

Lists which installed packages have newer versions available.


```shell
> dotnet list package --outdated

The following sources were used:
   nuget.org - https://api.nuget.org/v3/index.json
   Local - C:\NuGet\NuGetLocal

Project `ClassLibrary1` has the following updates to its packages
   [netcoreapp2.0]:
   Top-level Package      Requested   Resolved   Latest
   > EntityFramework      6.1.2       6.1.2      6.2.0
   > NUnit                2.4.0       2.6.4      3.8.1  
   > My.Sample.Pkg        2.1.3       4.1.0      4.1.0
```

Notes:
* *Important! Installed packages that are vulnerable or deprecated but not outdated will not be part of this command's output.*

- The `(D)` marker will be removed from this report.

*Combining the `--vulnerable` option with the `--outdated` option is (currently) not supported. When doing so, the following error message will be presented:*

```shell
> dotnet list package --outdated --vulnerable

Invalid command. Combining '--outdated' and '--vulnerable' options is not supported.
```

*Combining the `--outdated` option with the `--deprecated` option is (currently) not supported. When doing so, the following error message will be presented:*

```shell
> dotnet list package --outdated --deprecated

Invalid command. Combining '--outdated' and '--deprecated' options is not supported.
```

#### Deprecated

```shell
dotnet list package --deprecated
```

Lists which installed packages have been deprecated.

```shell
> dotnet list package --deprecated

The following sources were used:
   nuget.org - https://api.nuget.org/v3/index.json
   Local - C:\NuGet\NuGetLocal

Project `ClassLibrary1` uses the following deprecated packages
   [netcoreapp2.0]:
   Top-level Package              Requested  Resolved    Reason                 Alternative
   > My.Legacy.Package            2.0.0      2.0.0       Legacy                 My.Awesome.Package >= 3.0.0
   > My.Buggy.Package             1.1.0      1.1.0       Critical Bugs          My.NotBuggy.Package >= 2.0.0
   > My.Deprecated.Package        3.2.1      3.2.1       Other                  My.NotBuggy.Package >= 2.0.0
   > My.CompletelyBroken.Package  0.9.0      0.9.0       Legacy, Critical Bugs  My.Awesome.Package >= 1.0.0
```

Notes:
* *Important! Installed packages that are vulnerable or outdated but not deprecated will not be part of this command's output.*

* The table output for `--deprecated` should also include a new `Requested` column to improve clarity and for consistency with `--outdated` and `--vulnerable` commands.

*Combining the `--deprecated` option with the `--vulnerable` option is (currently) not supported. When doing so, the following error message will be presented:*

```shell
> dotnet list package --deprecated --vulnerable

Invalid command. Combining '--deprecated' and '--vulnerable' options is not supported.
```

*Combining the `--deprecated` option with the `--outdated` option is (currently) not supported. When doing so, the following error message will be presented:*

```shell
> dotnet list package --deprecated --outdated

Invalid command. Combining '--deprecated' and '--outdated' options is not supported.
```

#### Vulnerable

```shell
dotnet list package --vulnerable
```

Lists which installed packages have known vulnerabilities.

```shell
> dotnet list package --vulnerable

The following sources were used:
   nuget.org - https://api.nuget.org/v3/index.json
   Local - C:\NuGet\NuGetLocal

Project `ClassLibrary1` uses the following vulnerable packages
   [netcoreapp2.0]:
   Top-level Package              Requested  Resolved    Severity   Vulnerability
   > My.Vulnerable.Package        2.0.0      2.0.0       Low        https://URL-to-vuln-details
   > My.Fixed.Package             1.1.0      1.1.0       Critical   https://URL-to-vuln-details
```

Notes:
* *Important! Installed packages that are deprecated or outdated but not vulnerable will not be part of this command's output.*

* The Severity values will be colored default for Low, yellow for Moderate, and red for High and Critical (note that we can't represent this in GitHub markdown above).

*Combining the `--vulnerable` option with the `--deprecated` option is (currently) not supported. When doing so, the following error message will be presented:*

```shell
> dotnet list package --vulnerable --deprecated

Invalid command. Combining '--vulnerable' and '--deprecated' options is not supported.
```

*Combining the `--vulnerable` option with the `--outdated` option is (currently) not supported. When doing so, the following error message will be presented:*

```shell
> dotnet list package --vulnerable --outdated

Invalid command. Combining '--vulnerable' and '--outdated' options is not supported.
```

#### Flagged during/after restore

This is out of scope for the MVP of this feature.

#### Examples

* List vulnerable package references of a specific project (top-level dependencies only):

  ```shell
  dotnet list package MyProject.csproj --vulnerable
  ```

* List vulnerable package references, including transitive dependencies:

  ```shell
  dotnet list package --vulnerable --include-transitive
  ```

* List vulnerable package references for a specific target framework:

  ```shell
  dotnet list package --vulnerable --framework netcoreapp3.0
  ```

### Open Questions

* We need a single command to show *all updates, vulnerabilities and deprecations* as well. How? `nuget audit`?

## References

* [NuGet/Home#8087](https://github.com/NuGet/Home/issues/8087)
* [NuGet/Home#8716](https://github.com/nuget/home/issues/8716)
* [dotnet list package docs](https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-list-package)
