A checklist of npm security practices, from no install scripts to a 30 day cooldown
Collection of npm package manager Security Best Practices
At a glance
- What is it?
- The npm security best practices list is a curated document of seventeen practices in four groups, with copy and paste configuration for npm and pnpm at the top. Its core argument is that the most useful hardening is a cooldown on new versions and a refusal to run package lifecycle scripts at all.
- Who is it for?
- This list suits a JavaScript team that wants a defensible baseline for how packages are installed, published and upgraded, and it suits anyone who wants the configuration rather than the theory, since the npm and pnpm settings are given ready to paste.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 152 days ago.
- What is it written in?
- GitHub does not report a main language for this repository.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A document, with a configuration you can paste
This repository is a curated and practical list of security best practices for using npm packages, and the badging describes it as seventeen best practices with a last update in May. There is no code in it: a README, a contributing guide, a licence file, and.github/ and.claude/ directories.
The stated scope is five things: safe by default npm command line options, hardening against supply chain attacks, deterministic and secure dependency resolution, vulnerability scanning and package health signals, and instructions for the pnpm and bun package managers where applicable.
The context is stated in one sentence. Shai-Hulud, Nx and other incidents are a growing concern of supply chain security attacks and compromised npm packages, and the document exists to give developers practices around npm, package maintenance and secure local development to mitigate the risk. The repository topics list the Shai-Hulud attack and a detector for it among the other supply chain security terms.
What makes the document more useful than a list of principles is the top of it, which is a section titled as a copy and paste package manager config with the settings for npm and pnpm, collapsed into details blocks so the page stays readable. The npm file is short:
# npm security best practices
# Source: https://github.com/lirantal/npm-security-best-practices
# SECURITY: do not run any lifecycle scripts (postinstall) etc
ignore-scripts=true
# SECURITY: reject git-source dependencies (git+ssh:// etc)
allow-git=none
# SECURITY: block packages newer than 30 days
min-release-age=30Three settings, each with a comment explaining the reason. That is the entire configuration you need to get most of the benefit, and it is the part of the document that a team would actually apply on a Monday morning.
Why install scripts are the first item
The first practice is disabling post-install scripts, and the document opens that section with a warning rather than a rationale: post-install scripts are a common and recurring attack vector for supply chain attacks.
The named examples are specific. Recent attacks like Shai-Hulud and Nx, and long-standing attacks like event-stream, have all leveraged npm postinstall scripts to execute arbitrary code on a developer's machine during package installation, in order to exfiltrate sensitive data, trigger worm-like propagation, or perform other malicious activities. The mitigation is to configure npm to disable lifecycle scripts when installing packages so that any package, direct or indirect, cannot execute arbitrary code or commands on your system during installation.
The implementation advice is to set npm's ignore-scripts in the global configuration, so it applies to all projects on the machine:
$ npm config set ignore-scripts trueOr to disable them for an ad-hoc install from the command line:
$ npm install --ignore-scripts <package-name>The other package managers are handled differently, and the pnpm case is the interesting one. Beginning with version 10.0, pnpm disables postinstall scripts by default, and it offers an escape hatch to re-enable them or to set an explicit allow-list of packages permitted to run install scripts. The configuration lives in the workspace file rather than in a global setting:
# SECURITY: pnpm blocks install scripts by default, enabled explicitly for:
allowBuilds:
esbuild: true
rolldown: true
unrs-resolver: true
# SECURITY: fail the install if a dependency wants to run a build
# script that isn't in the allow-list above
strictDepBuilds: trueThat pair of settings is the most transferable idea in the document. Disabling scripts outright breaks packages that genuinely need to compile native code, and most teams solve that by turning the whole protection off. An explicit allow-list, combined with a setting that fails the install when an unlisted package wants to run a build, keeps the protection on and makes the exception visible in a file that is reviewed.
The document also has a section on running the scripts you need, and a section on the pnpm trust policy, which rejects a version whose publishing trust signals regressed.
The cooldown, and the tooling that understands it
The third practice is installing with a cooldown, and the configuration in the pnpm example expresses it in minutes:
# SECURITY: block packages newer than 30 days (43200 minutes)
minimumReleaseAge: 43200
# SECURITY: reject a version whose publishing trust signals regressed
trustPolicy: no-downgradeThe npm equivalent in the ini file is min-release-age=30, in days.
The reasoning is about the window in which a compromised release exists. A malicious version of a package is usually caught and unpublished within hours or days, and a thirty day delay means a team is unlikely to be the first adopter of a bad release. It also means a security fix is delayed by the same period, which is why the list does not stop at the package managers: it has separate sections for the upgrade tools, Snyk, Dependabot and Renovate, each with a cooldown configured so that the automated upgrade path also respects the window rather than pulling a new version the moment it appears.
The trust policy setting is a different idea and worth separating. It rejects a version whose publishing trust signals regressed, which is about the publisher rather than the release date, and the example configuration shows how to exclude specific versions when the signal is wrong, with the comment recommending that strict overrides are kept only when necessary and vetted. The commented example lists a couple of pinned versions, one of them a range of webpack versions.
This is the practice with the most operational consequence in the whole list, because a cooldown interacts with your release process, your security fixes and your developers' expectations. A team that ships weekly will feel it, and a team that ships monthly will barely notice.
The rest of the list, in four groups
The table of contents is grouped into npm practices, secure local development, npm maintainer practices and package health, and it is worth walking through what is in each group, because the spread tells you what the author thinks attackers go after.
The npm group covers disabling post-install scripts, blocking git-based dependencies, installing with a cooldown, hardening installs with security tools, preventing npm lockfile injection, using npm ci, avoiding blind package upgrades and hardening npx execution. The git dependency block is the other half of the first practice: allow-git=none in npm rejects git source dependencies such as git+ssh URLs, and the pnpm side is blockExoticSubdeps, which rejects dependencies sourced from git URLs. The hardening tools named are npq for hardening package installs and Socket Firewall, sfw, for blocking malicious packages.
The secure local development group is short. No plaintext secrets in .env files, and work in dev containers. The second one is a containment strategy rather than a package setting, and it is the recommendation that addresses the case where a dependency does get to run code.
The maintainer group is about being attacked yourself, with two factor authentication on npm accounts, publishing with provenance attestations, publishing with OIDC, and reducing your package dependency tree. That last one is the supply chain defence that most projects skip: a package with ten dependencies has ten chances to be compromised, and a package with none has none.
The package health group is about the other side of the ecosystem, with a section on consulting the Snyk security database, a section with the blunt title of not trusting the official npmjs.org registry, and a section on preventing dependency confusion attacks.
A document is not enforcement
The honest limitation of this repository is structural, and it is worth being clear about before anyone adopts it.
Nothing here is enforced by anything. There is no tool, no configuration file you can apply repository wide, and no CI check. The npm settings have to go into each repository's .npmrc, or into each developer's global npm config, and the pnpm settings have to go into each workspace file, and the two factor authentication, the provenance attestations and the OIDC publishing have to be configured on the npm account or in the release pipeline. The list is a set of decisions, and every one of them is a decision someone has to make and then remember.
That is also why the copy and paste block at the top matters so much. It is the difference between a list of seventeen practices and one line of configuration, and it is the part that a team can adopt without a project to run a tool.
The other limitation is that the list is a snapshot. It was last updated in May according to the badge, and the last push was on 2026-05-24. The package manager behaviours it depends on, in particular the pnpm version 10 defaults and the trust policy setting, are recent features of a moving tool, and a configuration copied today may need changing when those defaults change. The document lists seventeen practices and the badge counts seventeen, which means the numbering is stable and the content is meant to be edited in place rather than versioned.
There is a resources section with a FAQ at the end, and a contributing guide, and the repository carries a .claude/ directory, which suggests the document is now being maintained with the help of an assistant as well as by hand.
Editorial conclusion
This list suits a JavaScript team that wants a defensible baseline for how packages are installed, published and upgraded, and it suits anyone who wants the configuration rather than the theory, since the npm and pnpm settings are given ready to paste. It is the wrong choice if you want a tool that enforces the practices, because everything here has to be applied to each repository and to each developer's machine by hand, and a poor match if you are looking for a vulnerability database, since the list points at other services for that. Before applying it, read the post-install section first, because disabling install scripts breaks packages that genuinely need to compile, and the pnpm allow-list and strictDepBuilds settings are how you keep those working.
Frequently asked questions
How do I stop npm packages from running install scripts?
Set npm's ignore-scripts configuration globally with npm config set ignore-scripts true, or per install with npm install --ignore-scripts <package-name>. In an .npmrc file the setting is ignore-scripts=true, and pnpm blocks postinstall scripts by default from version 10.0 with an explicit allow-list for packages that need them.
What is the npm release cooldown setting?
For npm it is min-release-age=30 in .npmrc, which blocks packages newer than 30 days. The pnpm equivalent is minimumReleaseAge: 43200, expressed in minutes, and the list also shows how to configure a cooldown for Snyk, Dependabot and Renovate so automated upgrades respect the same window.
How do I keep packages that need to compile working after disabling install scripts?
In pnpm, use the allowBuilds setting in pnpm-workspace.yaml to name the packages permitted to run build scripts, and set strictDepBuilds to true so the install fails when an unlisted dependency wants to run a build. The list has a dedicated section on running the scripts you need.
What is in the npm maintainer security section?
Enabling two factor authentication for npm accounts, publishing with provenance attestations, publishing with OIDC, and reducing your package dependency tree, which the document treats as a supply chain defence in its own right since every dependency is another chance to be compromised.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/lirantal-npm-security-best-practices)Was this useful?