↓ Skip to main content
Security

Learning OSV, part 3: guided remediation with osv-scanner fix

·3 mins
Learning OSV - This article is part of a series.
Part 3: This Article
Finding 49 vulnerabilities is easy. Deciding which three lines to change so that most of them go away is the hard part. That is what osv-scanner fix tries to do.
Diagram comparing two fix strategies. in-place edits only the lockfile, upgrades lodash and axios within range, and fixes 7 of 50. relax edits package.json and relocks, upgrading jsonwebtoken to a new major, axios across 0.x and minimist by a patch, and fixes 50 of 50
in-place is the safe small win; relax fixes everything but chose a major upgrade.

In part 2 the scanner found 49 known vulnerabilities in a small Node project. This part tries the guided remediation command on it.

What it is
#

osv-scanner fix proposes “a small set of concrete changes” to your manifest and lockfile, and can apply them (guided remediation docs). It is listed as experimental. Today it supports:

FileStrategyWhat it changes
package-lock.jsonin-placeOnly the lockfile: swaps vulnerable versions for safe ones that still satisfy existing ranges
package.jsonrelaxRaises ranges in package.json where needed, then relocks the whole tree
pom.xmloverrideMaven: adds versions to <dependencyManagement> and bumps direct dependencies

It prints a warning first, and it is worth repeating: on an untrusted project, the package manager may run scripts or contact registries the project names. Run it only on code you trust.

Strategy 1: in-place (low risk)
#

osv-scanner fix --strategy=in-place -L package-lock.json
Found 50 vulnerabilities matching the filter
Can fix 7/50 matching vulnerabilities by changing 2 dependencies
UPGRADED-PACKAGE: lodash,4.17.15,4.18.1
UPGRADED-PACKAGE: axios,0.21.1,0.21.4
REMAINING-VULNS: 43

(The fix command counts 50; the scan showed 49 rows because two IDs for one path-to-regexp issue share a row.)

Only 7. package.json did not change at all. lodash and axios could move inside their caret ranges. Express could not help, and the reason is instructive: Express 4.17.1 pins its own dependencies to exact versions (qs 6.7.0, body-parser 1.19.0, …). No lockfile edit can move a package its parent has pinned exactly. The fix has to come from a newer Express.

Strategy 2: relax (fixes more, may break things)
#

osv-scanner fix --strategy=relax -M package.json -L package-lock.json
Can fix 50/50 matching vulnerabilities by changing 3 dependencies
UPGRADED-PACKAGE: axios,^0.21.1,^0.34.0
UPGRADED-PACKAGE: jsonwebtoken,^8.5.1,^9.0.3
UPGRADED-PACKAGE: minimist,1.2.5,^1.2.8
REMAINING-VULNS: 0

Three lines changed, all 50 gone. Express’s range did not even change: relocking resolved Express 4.22.3, the newest 4.x, which brings fixed versions of everything it pins. But read the three upgrades carefully:

ChangeRisk
jsonwebtoken 8 → 9Major version: breaking changes by definition
axios 0.21 → 0.34Under 0.x versioning, a minor bump can break things too
minimist 1.2.5 → ^1.2.8Patch-level; safe

A rescan proves the result:

Scanned ./package-lock.json file and found 92 packages
No issues found

Note the package count: 68 became 92. A relock reshapes the tree; newer versions bring new dependencies.

Keeping it under control
#

The flags I would use in practice (docs):

FlagUse
--upgrade-config=minorNever propose a major upgrade; can be set per package
--max-depth=1Only vulnerabilities in direct dependencies
--min-severity=7Ignore findings below a CVSS score
--ignore-devSkip devDependencies
--no-introduceReject patches that would add new vulnerabilities
--apply-top=NApply only the N best patches
--format=jsonOutput for a bot to turn into a pull request

And three caveats from the docs to keep in mind:

  • It edits your files. Commit first.
  • It does not reinstall node_modules. Run npm ci and your tests afterwards.
  • It does not read osv-scanner.toml; pass accepted risks with --ignore-vulns.

What I took from this part
#

  • in-place is a safe, small win (7 of 50 here): lockfile-only, no new ranges. Good for automatic PRs.
  • relax gets everything (50 of 50) but chose a major upgrade. That needs a human and the test suite.
  • Pinned transitive dependencies are why lockfile fixes stall: the fix is to upgrade the parent.
  • The tool proposes; the test suite and a reviewer decide.

References
#

Previous: part 2. Next: part 4, my recommendation.

Author
Samarthya
Engineer, learner, tinkerer. This is my trophy shelf of everyday work and leisure.
Learning OSV - This article is part of a series.
Part 3: This Article

Related

Learning OSV, part 2: scanning a project with OSV-Scanner

·4 mins
I picked four dependencies. The scanner found problems in eleven packages. That gap is the whole reason to scan lockfiles and not just package.json. Five dependencies I chose became 68 packages; 11 are affected, six of them only because Express pins them. Part 1 was about the OSV database. This part runs the scanner against a small project and reads the result.

Learning OSV, part 1: what osv.dev is and how to read a record

·4 mins
A CVE tells you that something is broken. It rarely tells you, in a way a machine can use, which package and which versions. OSV exists to answer exactly that. One record, read as data: the affected range runs from introduced 1.0.0 to fixed 1.2.6, so 1.2.5 is vulnerable and the upgrade target is 1.2.6. I am learning which free tools can carry real weight in a secure development life cycle. This short series is my proof of concept with OSV: the database, the scanner and its fix command. I run everything for real and keep the output. This part is about the concept and the website.

MITRE ATT&CK, plainly: tactics, technique IDs and a cheat card for each tactic

A football coach studies match footage of the other team: how they open, how they press, how they score. MITRE ATT&CK is the match footage of real attackers, cut into named and numbered moves. The OWASP Top 10 describes weaknesses in your software. ATT&CK describes what attackers do: how they get in, stay in, move around and take what they came for. You will see its IDs, such as T1190 or T1552.001, in threat reports, detection rules and, increasingly, in pipeline designs like the one in my SSDLC post. This post explains how to read them.