Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Guided Remediation Docs #827

Merged
merged 17 commits into from
Mar 5, 2024
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions docs/_sass/custom/custom.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Always show child pages in the navigation menu
// https://github.com/just-the-docs/just-the-docs/issues/245#issuecomment-656334333
.nav-list .nav-list-item > .nav-list {
display: block !important;
}

// Hide the child page expand arrow, since it doesn't do anything
.nav-list .nav-list-expander {
display: none !important;
}
117 changes: 2 additions & 115 deletions docs/experimental.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,127 +3,14 @@ layout: page
title: Experimental Features
permalink: /experimental/
nav_order: 8
has_children: true
---

# Experimental Features

{: .no_toc }

<details open markdown="block">
<summary>
Table of contents
</summary>
{: .text-delta }
- TOC
{:toc}
</details>
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.

## Offline mode

OSV-Scanner now supports offline scanning as an experimental feature. Offline scanning checks your project against a local database instead of calling the OSV.dev API.

### Specify database location

Our offline features require the use of a local database, the location of which is determined through the use of the `OSV_SCANNER_LOCAL_DB_CACHE_DIRECTORY` environment variable.

The local database file structure is in this form:

```
{local_db_dir}/
osv-scanner/
npm/all.zip
PyPI/all.zip
{ecosystem}/all.zip
```

Where `{local_db_dir}` can be set by the `OSV_SCANNER_LOCAL_DB_CACHE_DIRECTORY` environment variable.

If the `OSV_SCANNER_LOCAL_DB_CACHE_DIRECTORY` environment variable is _not_ set, OSV-Scanner will attempt to look for the database in the following locations, in this order:

1. The location returned by [`os.UserCacheDir`](https://pkg.go.dev/os#UserCacheDir)
2. The location returned by [`os.TempDir`](https://pkg.go.dev/os#TempDir)

The database can be [downloaded manually](./experimental.md#manual-database-download) or by using the [`--experimental-local-db` flag](./experimental.md#local-database-option).

### Offline option

The offline database flag `--experimental-offline` causes OSV-Scanner to scan your project against a previously downloaded local database. OSV-Scanner will not download or update the local database, nor will it send any project or dependency information anywhere. When a local database is not present, you will get an error message. No network connection is required when using this flag.

```bash
osv-scanner --experimental-offline ./path/to/your/dir
```

### Local database option

The local database flag `--experimental-local-db` causes OSV-Scanner to download or update your local database and then scan your project against it.

```bash
osv-scanner --experimental-local-db ./path/to/your/dir
```

### Manual database download

Instead of using the `--experimental-local-db` flag to download the database, it is possible to manually download the database.

A downloadable copy of the OSV database is stored in a GCS bucket maintained by OSV:
[`gs://osv-vulnerabilities`](https://osv-vulnerabilities.storage.googleapis.com)

This bucket contains zip files containing all vulnerabilities for each ecosystem at:
`gs://osv-vulnerabilities/<ECOSYSTEM>/all.zip`.

E.g. for PyPI vulnerabilities:

```bash
gsutil cp gs://osv-vulnerabilities/PyPI/all.zip .
```

You can also download over HTTP via https://osv-vulnerabilities.storage.googleapis.com/<ECOSYSTEM>/all.zip .

A list of all current ecosystems is available at
[`gs://osv-vulnerabilities/ecosystems.txt`](https://osv-vulnerabilities.storage.googleapis.com/ecosystems.txt).

Set the location of your manually downloaded database by following the instructions [here](./experimental.md#specify-database-location).

### Limitations

1. Commit level scanning is not supported.

## License scanning

OSV-Scanner supports license checking as an experimental feature. The data comes from the [deps.dev API](https://docs.deps.dev/api/).

### License summary

If you want a summary of your dependencies licenses, use the `--experimental-licenses-summary` flag:

```bash
osv-scanner --experimental-licenses-summary path/to/repository
```

### License violations

To set an allowed license list and see the details of packages that do not conform, use the `--experimental-licenses` flag:

```bash
osv-scanner --experimental-licenses="comma-separated list of allowed licenses" path/to/directory
```

Include your allowed licenses as a comma-separated list. OSV-Scanner recognizes licenses in SPDX format. Please indicate your allowed licenses using [SPDX license](https://spdx.org/licenses/) identifiers.

#### License violations example

If you wanted to allow the following licenses:

- [BSD 3-Clause "New" or "Revised" License](https://spdx.org/licenses/BSD-3-Clause.html)
- [Apache License 2.0](https://spdx.org/licenses/Apache-2.0.html)
- [MIT](https://spdx.org/licenses/MIT.html)

Your command would be in this form:

```bash
osv-scanner --experimental-licenses="BSD-3-Clause,Apache-2.0,MIT" path/to/directory
```
225 changes: 225 additions & 0 deletions docs/guided-remediation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
---
layout: page
oliverchang marked this conversation as resolved.
Show resolved Hide resolved
title: Guided Remediation
permalink: /experimental/guided-remediation/
parent: Experimental Features
nav_order: 3
---

# Guided Remediation

Experimental
{: .label }

{: .no_toc }

<details open markdown="block">
<summary>
Table of contents
</summary>
{: .text-delta }
- TOC
{:toc}
</details>

The `osv-scanner fix` subcommand leverages [deps.dev](https://deps.dev) to provide automated and guided remediation of vulnerabilities in your project's dependencies by suggesting upgrades to dependencies.
oliverchang marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This now feels a bit repetitive. How about folding this into the previous paragraph, and moving the deps.dev mention to the resolution point below?

Guided remediation (`osv-scanner fix`) aims to help developers with ....
...

...
- Resolution and analysis of the entire transitive graph (leveraging deps.dev)...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


Currently, only npm `package.json` manifests and `package-lock.json` lockfiles are supported.

{: .note }
This feature is experimental and may change in future updates.
michaelkedar marked this conversation as resolved.
Show resolved Hide resolved

## Basic usage: interactive mode

Interactive mode provides a step-by-step process to understand and fix vulnerabilities in your project.

To run it, you can use the following command:

```bash
osv-scanner fix -M path/to/package.json -L path/to/package-lock.json
```

The command will launch the Guided Remediation TUI and begin scanning your manifest and lockfile for vulnerabilities. Use the arrow keys to navigate menu items and the `ENTER` key to select. `TAB` can be used to switch to and from the information panel of each option.

![Screenshot of the initial interactive results screen, showing found vulnerabilities and the potential remediation approaches](images/guided-remediation-result.png)
another-rex marked this conversation as resolved.
Show resolved Hide resolved

{: .highlight }

> The initial screen allows you to change the vulnerability selection criteria. Each correspond to a [vulnerability selection flag](#vulnerability-selection):
>
> - Max dependency depth: `--max-depth`
> - Min CVSS score: `--min-severity`
> - Include dev only: `--ignore-dev`
michaelkedar marked this conversation as resolved.
Show resolved Hide resolved

From the first results screen, you can select which of the two remediation strategies to attempt.

## In-place lockfile remediation

'In-place' remediation involves replacing vulnerable versions of packages in your lockfile with non-vulnerable versions, while still respecting the existing constraints for that dependency. This approach is usually less risky, but often fixes the least vulnerabilities.
michaelkedar marked this conversation as resolved.
Show resolved Hide resolved

Selecting the "Modify lockfile in place" option will bring you to the in-place information page. From here, you can see which vulnerabilities can and cannot be resolved by this strategy. By default, every possible in-place patch will be chosen to be applied. You may instead choose which subset of patches you wish to apply.

![Screenshot of the interactive in-place results screen](images/guided-remediation-in-place-results.png)

![Screenshot of the interactive in-place patch selection screen](images/guided-remediation-in-place-choose.png)

If you wish to apply the proposed in-place patches, select the "Write" option to update your lockfile with the new dependency versions.

{: .warning }
another-rex marked this conversation as resolved.
Show resolved Hide resolved
The subcommand cannot revert the changes it makes to your lockfile. Make sure you backup your lockfile beforehand.
michaelkedar marked this conversation as resolved.
Show resolved Hide resolved

{: .note }
Writing these changes will not reinstall your dependencies. You'll need to run `npm ci` (or equivalent) separately.

## Relock and relax direct dependency remediation

Relocking recomputes your entire dependency graph based on your manifest file, taking the newest possible versions of all your required packages. This causes a large number of changes to your dependency graph, which potentially carries a larger risk of breakages.
oliverchang marked this conversation as resolved.
Show resolved Hide resolved

Selecting the "Relock" option will bring you to the relock information page. Here, you can see which vulnerabilities are present after relocking.

In addition to relocking, it may be possible to further remove vulnerabilities by bumping the required version constraints of your direct dependencies. You may choose to apply these patches by selecting them on the relock page then choosing the "Apply pending patches" option. The dependency graph will then be recomputed and you may continue to select more options.

![Screenshot of the interactive relock results screen with some relaxation patches selected](images/guided-remediation-relock-patches.png)

The relaxation patches are presented in order of effectiveness, with patches that resolve the most vulnerabilities with the least amount of dependency change shown first.

If you wish to apply your current relock & relaxation changes, select the "Write" option to update your manifest file with the new requirements and regenerate your lockfile (if provided).

{: .warning }
The subcommand cannot revert the changes it makes to your manifest and lockfile. Make sure you backup your files beforehand.

{: .note }

> The `package-lock.json` file is regenerated by first deleting the existing `package-lock.json` & `node_modules/` directory, then running `npm install --package-lock-only`. To recreate `node_modules/`, you'll need to run `npm ci` separately
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This bit feels a bit confusing to me. The first sentence does not make it clear that node_modules/ will be NOT be recreated along with package-lock.json. We should clarify that.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've changed it to be more explicit, but I'm not sure if I've made it any less confusing.

>
> The `--relock-cmd` flag can be used to change the executed install command.

## Non-interactive mode

To enable usage in scripting and automation, we provide a non-interactive mode:
oliverchang marked this conversation as resolved.
Show resolved Hide resolved

```bash
osv-scanner fix --non-interactive --strategy=in-place -M path/to/package.json -L path/to/package-lock.json
```

```bash
osv-scanner fix --non-interactive --strategy=relock -M path/to/package.json -L path/to/package-lock.json
```

By default, non-interactive mode will resolve and apply every compatible in-place/relaxation patch according to the selected strategy. If you wish to limit the number of patches applied, you can use the `--apply-top=N` flag. Subsets of patches will be chosen in the same order as they would be presented in the interactive mode. For further control over the patches that should be applied, use the [remediation flags](#remediation-flags).

### Sample outputs

{: .note }
The output format might change with minor version updates.

<details markdown="1">
<summary><b>In-place strategy</b></summary>
```bash
osv-scanner fix --non-interactive --strategy=in-place -M path/to/package.json -L path/to/package-lock.json
```
```
Scanning path/to/package-lock.json...
Found 52 vulnerabilities matching the filter
Can fix 23/52 matching vulnerabilities by changing 21 dependencies
UPGRADED-PACKAGE: lodash,4.17.20,4.17.21
UPGRADED-PACKAGE: minimist,1.2.0,1.2.8
UPGRADED-PACKAGE: acorn,5.7.3,5.4.1
UPGRADED-PACKAGE: acorn,6.0.2,6.4.2
UPGRADED-PACKAGE: acorn,7.1.0,7.4.1
UPGRADED-PACKAGE: ansi-regex,3.0.0,3.0.1
UPGRADED-PACKAGE: dat.gui,0.7.3,0.7.9
UPGRADED-PACKAGE: get-func-name,2.0.0,2.0.2
UPGRADED-PACKAGE: glob-parent,5.0.0,5.1.2
UPGRADED-PACKAGE: json5,2.1.0,2.2.3
UPGRADED-PACKAGE: minimist,1.2.5,1.2.8
UPGRADED-PACKAGE: node-fetch,2.6.6,2.7.0
UPGRADED-PACKAGE: path-parse,1.0.6,1.0.7
UPGRADED-PACKAGE: pathval,1.1.0,1.1.1
UPGRADED-PACKAGE: qs,6.5.2,6.5.3
UPGRADED-PACKAGE: semver,5.5.1,5.7.2
UPGRADED-PACKAGE: semver,5.6.0,5.7.2
UPGRADED-PACKAGE: semver,6.3.0,6.3.1
UPGRADED-PACKAGE: ws,6.2.1,6.2.2
UPGRADED-PACKAGE: ws,7.1.2,7.5.9
UPGRADED-PACKAGE: y18n,4.0.0,4.0.3
REMAINING-VULNS: 29
UNFIXABLE-VULNS: 29
Rewriting path/to/package-lock.json...
```
</details>

<details markdown="1">
<summary><b>Relock strategy</b></summary>
```bash
osv-scanner fix --non-interactive --strategy=relock --apply-top=2 -M path/to/package.json -L path/to/package-lock.json
```
```
Resolving path/to/package.json...
Found 11 vulnerabilities matching the filter
Can fix 4/11 matching vulnerabilities by changing 2 dependencies
UPGRADED-PACKAGE: mocha,^5.2.0,^9.2.2
UPGRADED-PACKAGE: @google-cloud/cloudbuild,^2.6.0,^3.10.0
REMAINING-VULNS: 7
UNFIXABLE-VULNS: 3
Rewriting path/to/package.json...
Shelling out to regenerate lockfile...
Executing `npm install --package-lock-only`...
[ npm output ]
```
</details>

## Remediation flags

The `fix` subcommand has a number of flags to allow you to control which vulnerabilities and patches may be considered during remediation.

### Vulnerability selection

The following flags may be used to filter which vulnerabilities will be selected for remediation:

- `--max-depth=<value>`: The maximum dependency depth to consider vulnerabilities from.

For example, `--max-depth=1` will only consider vulnerabilities affecting direct dependencies, while `--max-depth=2` will consider up to the direct dependencies of your direct dependencies. Setting `--max-depth=-1` will consider all dependencies, regardless of depth.

- `--min-severity=<value>`: The minimum CVSS score of vulnerabilities to consider.

For example, `--min-severity=7.5` will consider only vulnerabilities with CVSS a score of 7.5 and above. If the OSV record for the vulnerability does not have a CVSS score, it will **not** be excluded.

- `--ignore-dev`: Whether to exclude vulnerabilities from dependencies that are only used in `devDependencies`.
- `--ignore-vulns=<comma-separated list of IDs>`: A list of OSV IDs to exclude from consideration.
- `--vulns=<comma-separated list of IDs>`: An explicit list of OSV IDs that should exclusively be considered, as long as the other criteria are satisfied.

A vulnerability is only considered if it satisfies all the conditions set by these flags.

### Dependency upgrade options

The following flags may be used to limit the patches allowed for your dependencies:

- `--disallow-major-upgrades`: Do no allow patches that would result in the major version number of any dependency from being changed.
- `--disallow-package-upgrades=<comma-separated list of package names>`: Do no allow patches to any of the listed packages.

### Data source

By default, we use the [deps.dev API](https://docs.deps.dev/api/v3alpha/) to find version and dependency information of packages during remediation.

If instead you'd like to use your ecosystem's native registry API (e.g. `https://registry.npmjs.org`), you can use the `--data-source=native` flag. `osv-scanner fix` will attempt to use the authentication specified by the native tooling (e.g. `npm config`)

{: .highlight }
If your project uses mirrored or private registries, you will need to use `--data-source=native`

{: .note }

> The subcommand caches the requests it makes in `package.json.resolve.deps` (deps.dev) and `package.json.resolve.npm` (native npm).
>
> The native npm cache will store the addresses of private registries used, though not any authentication information.

## Known issues

- The subcommand does not use the `osv-scanner.toml` configuration. Use the `--ignore-vulns` flag instead.

### npm

- Non-registry dependencies (local paths, URLs, Git, etc.) are not evaluated.
- `peerDependencies` are not properly considered during dependency resolution (treated as if using `--legacy-peer-deps`).
- `overrides` are ignored during dependency resolution.
- The `node_modules/` in workspaces are not deleted when relocking, which may impact the resulting dependency graph.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, should we add a section specifically to call out workspaces and how we handle that?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Expanded upon the workspaces in its own sub-sub-sub-heading :)

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/guided-remediation-result.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading