Security
Security features, defaults, and supply-chain hardening
snpm ships with security-first defaults: install scripts are blocked, registry credentials are scoped to the announcing registry origin, lockfiles record integrity hashes, and audit can both surface advisories and attempt to fix them.
Install scripts blocked by default
Install scripts (preinstall, install, postinstall) for dependencies are blocked unless explicitly allowed. This is the single biggest attack vector in the npm ecosystem and snpm closes it by default.
Allow specific packages via env var:
export SNPM_ALLOW_SCRIPTS="esbuild,sharp,@swc/core"Or via workspace config:
onlyBuiltDependencies:
- esbuild
- sharp
ignoredBuiltDependencies:
- fseventsRoot project and workspace-member lifecycle scripts (the ones you wrote) do run during install — preinstall → install → postinstall → prepare.
After changing the allow-list, run snpm rebuild to apply it to packages that already extracted.
Only allow packages you trust. puppeteer, playwright, sharp, esbuild, @swc/core are common cases — they download platform binaries during install. When in doubt, look at the package's install script before allowing it.
Minimum package age
SNPM_MIN_PACKAGE_AGE_DAYS=N makes snpm ignore versions published within the last N days.
export SNPM_MIN_PACKAGE_AGE_DAYS=7Why this matters:
- Zero-day publishes — malicious versions often get yanked within hours; waiting a few days drastically reduces the chance of installing a compromised release.
- Broken releases — hastily published versions with critical bugs get patched quickly; waiting steers you to the patched build.
- Compromised maintainer accounts — gives the community time to detect and report unauthorized publishes.
Recommended values:
- Development: unset.
- CI/staging:
3. - Production:
7.
Trade-off: brand-new packages (and brand-new patches) won't be installable until they age. Combine with --frozen-lockfile so CI never silently picks up newer versions either.
Lockfile and integrity
snpm-lock.yaml records each package's tarball URL and integrity hash. The hash is verified against the bytes snpm downloads before the package is unpacked.
node_modules/.snpm-integrity holds a lockfile-derived hash of the install plan. On the next install, snpm reads this file first; if it still matches, the install completes in tens of milliseconds without touching the registry or unpacking anything.
In CI, use --frozen-lockfile (or SNPM_FROZEN_LOCKFILE=1):
snpm install --frozen-lockfileA drifted lockfile becomes a hard failure, not a silent upgrade.
Registry authentication
snpm login runs a web flow by default and stores the resulting Bearer token in ~/.snpmrc. Tokens never end up in package.json or snpm-lock.yaml.
snpm login
snpm login --registry https://npm.mycompany.com
snpm login --scope @myorg --registry https://npm.mycompany.comFor CI, set a token via environment variable:
export NODE_AUTH_TOKEN=...
# or
export NPM_TOKEN=...
# or
export SNPM_AUTH_TOKEN=...For Basic auth, set NPM_CONFIG__AUTH=<base64-of-user:pass>.
To force auth on every request (even for public scopes), enable always-auth:
always-auth=trueexport SNPM_ALWAYS_AUTH=1Scoped registries
@myorg:registry=https://npm.myorg.com/
//npm.myorg.com/:_authToken=${MYORG_TOKEN}Tarball origin scoping
When a registry response includes a tarball URL on a different host, snpm does not send the registry's credentials to that other host. Credentials are scoped to the announcing registry origin. This prevents a compromised or malicious registry from steering snpm into leaking your auth token to an attacker-controlled host.
Audit
snpm audit # report vulnerabilities
snpm audit --audit-level high # critical/high only
snpm audit --fix # try to upgrade to a fixed version
snpm audit --format sarif > a.sarif
snpm audit -P # production only
snpm audit --ignore-cve CVE-2024-12345 --ignore-unfixable--format sarif produces SARIF that GitHub and GitLab security dashboards consume directly — see CI/CD for a workflow example.
When the registry's audit endpoint itself fails, add --ignore-registry-errors to keep CI green and rely on other security scanners.
Publishing safely
snpm pack (and snpm publish before uploading) runs an inspection that surfaces blocking findings — files outside the package root, missing README, oversized files, suspicious binaries. Re-run with --dry-run and --list to see the full tarball:
snpm pack --dry-run --listOverride a specific blocking finding for one publish:
snpm publish --allow-risk OVERSIZED_FILEsnpm publish --otp 123456 carries through OTP codes for accounts with two-factor auth.
Best practices
- Commit
snpm-lock.yamland use--frozen-lockfilein CI. - Set
SNPM_MIN_PACKAGE_AGE_DAYS=7for production-bound CI. - Keep the script allow-list minimal — only the dependencies that actually need to compile native bits.
- Run
snpm auditin CI with--format sarif, gated on--audit-level highfor hard failures. - Use scoped registries with
always-authfor private packages. - Rotate registry tokens periodically and prefer short-lived CI tokens over long-lived ones.
- Use
snpm why <pkg>to investigate suspicious transitive dependencies before allowing them.
Reporting vulnerabilities
If you find a security vulnerability in snpm itself, please report it via GitHub Security Advisories.