Skip to content

Commit 7bf7fc2

Browse files
security: implement NPM supply chain attack protection with 3-day age gate (#846)
## **Description** Implements critical NPM supply chain attack protection by adding a 3-day minimum age gate for package installations. This security enhancement prevents the installation of freshly published packages that could contain malicious code, providing a crucial defense against supply chain attacks. The implementation follows [instructions from the security team](https://consensys.slack.com/archives/C0318JSUBM3/p1760719594306489) for protecting against ongoing NPM supply chain threats, requiring all packages to be at least 3 days old before installation while maintaining exceptions for trusted MetaMask and LavaMoat packages. ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/DSYS-242 ## **Manual testing steps** - [x] Verify yarn version upgraded to 4.10.2+ for age gate support - [x] Run `yarn install` to confirm age gate configuration works without blocking existing dependencies - [x] Confirm `@metamask/*` and `@lavamoat/*` packages are pre-approved and can bypass age restrictions - [x] Test that the repository builds and runs correctly with new yarn version - [ ] Attempt to install a very recent package to verify age gate blocks it (optional security validation) ## **Screenshots/Recordings** Not applicable - this is a security infrastructure change without visual components. ## **Pre-merge author checklist** - [x] I have reviewed the Files changed tab - [x] Yarn version updated to 4.10.2 to support npmMinimalAgeGate feature - [x] Added npmMinimalAgeGate: 4320 (3 days in minutes) to .yarnrc.yml - [x] Added npmPreapprovedPackages list with trusted @metamask/* and @lavamoat/* packages - [x] Verified yarn install works correctly with new configuration - [x] All existing scripts and workflows continue to function - [ ] I have tested this PR on my local machine ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. ## **Security Impact** **Protection Against Supply Chain Attacks:** - **3-Day Age Gate**: Prevents installation of packages newer than 3 days, allowing community time to identify and report malicious packages - **Trusted Package Bypass**: @metamask/* and @lavamoat/* packages can bypass restrictions for urgent security updates - **Zero Developer Friction**: Protection works transparently without changing development workflows **Before:** - Any NPM package could be installed immediately upon publication - Vulnerable to fresh supply chain attacks and malicious package injections - No protection against compromised packages in the first hours/days **After:** - All external packages must be at least 72 hours old before installation - Trusted MetaMask and LavaMoat packages can bypass for emergency updates - Automatic protection against fresh malicious packages with zero workflow impact ## **Technical Details** **Configuration Changes:** - **package.json**: Updated `packageManager` from `[email protected]` to `[email protected]` - **.yarnrc.yml**: Added `npmMinimalAgeGate: 4320` (3 days in minutes) - **.yarnrc.yml**: Added `npmPreapprovedPackages` with `["@metamask/*", "@lavamoat/*"]` **Yarn Lock Updates:** - Minor typescript patch hash update (expected with yarn version change) - No breaking dependency changes **Security Alignment:** - Follows MetaMask security best practices for supply chain protection - Implements defense-in-depth strategy alongside existing @lavamoat/allow-scripts protection - Compatible with existing LavaMoat yarn plugin configuration <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Enable a 3‑day NPM package age gate in Yarn and bump Yarn to 4.10.3, updating constraints and lockfile accordingly. > > - **Config/Security**: > - Add `npmMinimalAgeGate: 4320` and `npmPreapprovedPackages` (`@metamask/*`, `@lavamoat/*`) in `.yarnrc.yml`. > - **Tooling**: > - Update `packageManager` from `[email protected]` to `[email protected]` in `package.json`. > - Update `yarn.config.cjs` constraint to expect `[email protected]`. > - **Lockfile**: > - Update `yarn.lock` TypeScript patch resolution/checksum. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 4d63fe0. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent 721f31b commit 7bf7fc2

File tree

4 files changed

+13
-4
lines changed

4 files changed

+13
-4
lines changed

.yarnrc.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,12 @@ plugins:
1717
spec: 'https://raw.githubusercontent.com/LavaMoat/LavaMoat/main/packages/yarn-plugin-allow-scripts/bundles/@yarnpkg/plugin-allow-scripts.js'
1818

1919
nmHoistingLimits: none
20+
21+
# NPM Supply Chain Attack Protection
22+
# Minimum age gate: only allow packages older than 3 days (4320 minutes)
23+
npmMinimalAgeGate: 4320
24+
25+
# Pre-approved packages that can bypass the age gate
26+
npmPreapprovedPackages:
27+
- '@metamask/*'
28+
- '@lavamoat/*'

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@
128128
"typescript-eslint": "^8.7.0",
129129
"yargs": "^17.7.2"
130130
},
131-
"packageManager": "yarn@4.2.2",
131+
"packageManager": "yarn@4.10.3",
132132
"engines": {
133133
"node": "^18.18 || >=20"
134134
},

yarn.config.cjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ module.exports = defineConfig({
207207
if (isChildWorkspace) {
208208
workspace.unset('packageManager');
209209
} else {
210-
expectWorkspaceField(workspace, 'packageManager', 'yarn@4.2.2');
210+
expectWorkspaceField(workspace, 'packageManager', 'yarn@4.10.3');
211211
}
212212

213213
// All packages must specify a minimum Node.js version of 18.18.

yarn.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20703,11 +20703,11 @@ __metadata:
2070320703

2070420704
"typescript@patch:typescript@npm%3A5.5.4#optional!builtin<compat/typescript>":
2070520705
version: 5.5.4
20706-
resolution: "typescript@patch:typescript@npm%3A5.5.4#optional!builtin<compat/typescript>::version=5.5.4&hash=b45daf"
20706+
resolution: "typescript@patch:typescript@npm%3A5.5.4#optional!builtin<compat/typescript>::version=5.5.4&hash=379a07"
2070720707
bin:
2070820708
tsc: bin/tsc
2070920709
tsserver: bin/tsserver
20710-
checksum: 10/2c065f0ef81855eac25c9b658a3c9da65ffc005260c12854c2286f40f3667e1b1ecf8bdbdd37b59aa0397920378ce7900bff8cb32e0f1c7af6fd86efc676718c
20710+
checksum: 10/746fdd0865c5ce4f15e494c57ede03a9e12ede59cfdb40da3a281807853fe63b00ef1c912d7222143499aa82f18b8b472baa1830df8804746d09b55f6cf5b1cc
2071120711
languageName: node
2071220712
linkType: hard
2071320713

0 commit comments

Comments
 (0)