Add .npmrc with security hardening settings#51
Conversation
Security hardening: ignore-scripts prevents malicious install scripts from running during npm install, and save-exact pins dependency versions. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds repository-level npm configuration intended to harden installs by disabling lifecycle scripts and enforcing exact version pinning for dependencies.
Changes:
- Introduces
.npmrcwithignore-scripts=trueto prevent running install/postinstall scripts duringnpm install/npm ci. - Enables
save-exact=trueso newly added dependencies are saved with exact versions.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| ignore-scripts=true | ||
| save-exact=true |
There was a problem hiding this comment.
Code Review
This PR adds a .npmrc file with ignore-scripts=true and save-exact=true as a security hardening measure, but the ignore-scripts=true setting will break the installation of 6 packages in the dependency tree that rely on lifecycle scripts (esbuild, @tailwindcss/oxide, @parcel/watcher, fsevents, playwright/fsevents, unrs-resolver).
Inline comments: 3 discussions added
Overall Assessment:
| @@ -0,0 +1,2 @@ | |||
| ignore-scripts=true | |||
There was a problem hiding this comment.
Critical Issue: ignore-scripts=true will break installation of 6 packages in the current dependency tree that rely on lifecycle scripts to function. The package-lock.json shows the following packages have hasInstallScript: true:
node_modules/esbuild— downloads the platform-specific binary via its install script (required by Vite)node_modules/@tailwindcss/oxide— native Rust binary installed vianapi-postinstallnode_modules/@parcel/watcher— native file-watching binarynode_modules/unrs-resolver— native resolver binarynode_modules/fsevents(×2) — macOS native file system events
With this setting, npm install will silently skip these scripts and the packages will be partially installed, causing build/test failures (e.g., vite and tailwindcss will fail to start because their native binaries are missing).
The .npmrc allowlist syntax shown in the PR description (lifecycle-script-allowed[]=esbuild) is not a real npm feature — npm has no such option. The correct mitigation is either:
- Remove
ignore-scripts=trueand rely onnpm audit/ a tool like Diffend (which the repo already uses viarun-diffend.yml) for supply chain defense, or - Use
npm install --ignore-scriptsonly in specific CI steps that don't need native binaries, and document exactly which steps those are.
| @@ -0,0 +1,2 @@ | |||
| ignore-scripts=true | |||
| save-exact=true | |||
There was a problem hiding this comment.
Important Issue: save-exact=true pins the version written into package.json when running npm install <package>, but it has no effect on the existing package.json entries which already use range specifiers (e.g., "^7.1.12"). The existing ranges will still be resolved to the latest matching version unless the developer also updates all existing package.json entries to exact versions. Since package-lock.json already provides reproducibility for all collaborators and CI, the practical benefit here is marginal and only applies to future npm install <pkg> invocations. Consider whether this aligns with the team's actual versioning workflow, or whether tightening package.json ranges directly would be more effective.
| @@ -0,0 +1,2 @@ | |||
| ignore-scripts=true | |||
There was a problem hiding this comment.
Important Issue: The CI workflows (run-tests.yml, run-lint.yml) use npm install (not npm ci), which means they will be affected by this .npmrc setting immediately. With ignore-scripts=true active, the npm install step in those workflows will install broken packages and the subsequent build/test steps will fail. The workflows that already use npm ci (check-types.yml, deploy-storybook.yml, publish.yml, react-compat.yml) are equally affected. This is a blocking change for all CI pipelines.
Summary
.npmrcwithignore-scripts=trueandsave-exact=trueignore-scripts=trueprevents arbitrary code execution duringnpm install(supply chain defense)save-exact=truepins exact dependency versions for reproducible buildsIf a package requires install scripts
Add a per-package allowlist in
.npmrc:Or run one-off with:
Context
Part of an org-wide security hardening initiative for all npm-based repositories.