overrides / resolutions dependency swap
During dependency resolution in npm install / yarn install
- Lives in
overrides (npm) or resolutions (Yarn) field in package.json- Attacker needs
- Supply-chain foothold
- Lifecycle
- InstallStartupyour codeModule loadRuntimeREPL
Runs while dependencies download and build. The app has never started.
How it runs
npm (v8.3+) has overrides, and Yarn has resolutions. Both force specific versions of transitive dependencies, the packages you don't directly depend on that sit deep in the tree. The stated purpose is patching CVEs without waiting for upstream.
{
"overrides": {
"lodash": "npm:evil-lodash@1.0.0"
}
}
That single line replaces every lodash across your entire tree with evil-lodash. The version looks legitimate. The npm: alias makes npm fetch a completely different package while your code still does require('lodash'). Yarn's resolutions can even point at an arbitrary tarball URL.
Overrides can target specific paths (express > qs) to stay narrow. The real danger is that people expect them in package.json. Nobody questions a commit message like "pinned lodash to fix CVE-2024-XXXXX", and the impact is invisible to anyone not diffing the lockfile.
Defend
Diff the lockfile, not just package.json; scrutinize npm: aliases and URL specifiers in overrides; require review for transitive pins.