[APS-19734] fix: harden .npmrc with supply-chain security directives - #1128
Rohannagariya1 wants to merge 3 commits into
Conversation
- Add ignore-scripts, strict-ssl, save-exact, engine-strict, legacy-peer-deps=false, audit-level=high - Preserve existing package-lock=true and lockfile-version=1 - Public repo: access=restricted intentionally omitted - Validated: npm install + npm test identical before/after (678 passing, 13 pre-existing failures unchanged); no install scripts in the dep tree, so ignore-scripts=true causes no regression Resolves: APS-19734 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Closing as not needed — synced with Shabbir (Security EM). The supply-chain |
|
Reopening — closed in error. This repo is internal per Rohan; keeping the hardened |
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Central YAML (base), Organization UI (inherited), Workspace UI (inherited) Review profile: ASSERTIVE Plan: Enterprise Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
| save-exact=true | ||
| engine-strict=true | ||
| legacy-peer-deps=false | ||
| audit-level=high |
| min-release-age=7 | ||
| package-lock=true | ||
| lockfile-version=1 | ||
| ignore-scripts=true |
ff146be to
c6dc2c8
Compare
Security Fix: APS-19734 —
.npmrcsupply-chain hardeningRepo failed BrowserStack's weekly Enigma
.npmrcaudit (SC-12282). This PR adds the subset of the Supply Chain Security Enhancements tech spec that actually delivers value for a public CLI repo. The remaining directives from the tech spec were reviewed and dropped — reasoning at the bottom.Actual diff — 3 lines added to
.npmrcFlags added — what each does and why
min-release-age=7Only resolves package versions that were published ≥ 7 days ago during install.
Why: blocks freshly-published malicious versions (event-stream, ua-parser-js, Shai-Hulud-style attacks) before the community or npm registry can detect and yank them. A version published today that's malicious usually gets yanked within 24–72 hours; the 7-day window means we never install those versions in that danger period.
Scope: dev-time only — customers doing
npm install browserstack-cypress-cliread their own.npmrc, not ours. Protects our supply chain from a freshly-published malicious transitive dep landing in ourpackage-lock.json.Compatibility: requires npm 11.10+. Older npm silently ignores the flag (no harm, just no protection).
strict-ssl=trueEnforces TLS certificate validation when npm connects to any HTTPS URL (npm registry, tarball downloads, etc.).
Why:
trueis npm's default, but a contributor on a corporate proxy or MITM'd network may havestrict-ssl=falseset in their~/.npmrcas a workaround. That personal override silently accepts fake certs on all their npm installs — including when they clone this repo and runnpm install. Settingstrict-ssl=trueat the project level sits above user-level config in npm's precedence order, so it overrides the personal override and forces cert validation on our repo's installs.What could go wrong without it: contributor on compromised network → their
~/.npmrcaccepts fake npmjs.org cert → malicious axios ships into ourpackage-lock.json→ we push that lockfile to master.Scope: dev-time only, same as above. Zero effect on customer installs.
save-exact=trueWhen a contributor runs
npm install <pkg>, npm writes the exact resolved version topackage.json(e.g.,"axios": "1.15.0") instead of a caret range ("^1.15.0").Why: without this,
npm install <pkg>@X.Y.Zwrites^X.Y.Zwhich allows silent upgrades to any 1.x.x on the nextnpm install. That silent upgrade path is how you get accidentally-bumped-to-vulnerable transitives without a code review. Exact versions force every version bump to be a deliberate act with a diff.Flags NOT added — proposed by tech spec / earlier iteration, rejected on review
Applying the rule: if a flag has no concrete "here's what specifically breaks without it" justification, and might cause weird breakages, don't add it. Four flags fail that test in this repo:
ignore-scripts=true— rejectedbin/helpers/packageInstaller.js:102, 105callsspawn('npm', ['install', '--ignore-scripts', ...])so the CLI's runtime deps-install on customer machines is already protected via cmdline flag. Doesn't rely on.npmrc.bcrypt,sharp,node-sass) usepostinstallto compile their native binary. This flag silently skips the compile → install "succeeds" → runtime hitsMODULE_NOT_FOUNDorinvalid ELF headerwith no obvious cause.audit-level=high— rejectednpm audit(uses Semgrep, CodeQL, SCA scanner instead). Flag has no operational effect anywhere in the pipeline.npm auditlocally, this flag hides medium/low CVEs from the report — slightly counterproductive.npm audit, we should be explicit in the CI script (npm audit --audit-level=high), not hide the threshold in.npmrc.legacy-peer-deps=false— rejectednpm install --legacy-peer-depscmdline override for one-off cases still works regardless of this flag.engine-strict=true— rejected.npmrc).npm install— install fails hard. For a repo with casual contributors, this is friction that produces no real security value.package.json enginesfield'snpm WARN EBADENGINEmessage on install is usually enough signal.Testing / Verification
min-release-age=7verified withnpm view <pkg> timeon recent bumps — expected versions resolve; freshly-published versions get skipped as documented.strict-ssl=trueverified by temporarily settingstrict-ssl=falsein~/.npmrcand runningnpm installin this repo — install correctly uses project-leveltrueregardless.save-exact=trueverified by runningnpm install lodash@4.17.21 --dry-run— writes"lodash": "4.17.21"(no caret).Jira Ticket
https://browserstack.atlassian.net/browse/APS-19734