Companion guide for the Chainguard npm package and images npm v12 PSA.
Who should read this
Read this page if you install npm packages inside a Chainguard Node image, or if you install the Chainguard npm package with apk and run npm during a build or at runtime.
“These behavior changes come from upstream npm, not from Chainguard. Your Chainguard image or package inherits them when it updates to npm v12.”
Am I affected, and how do I tell
You are most likely affected if your build or runtime does any of the following:
Runs dependency install scripts. Common examples are native node-gyp modules such as sharp, bcrypt, or better-sqlite3, and tools such as Cypress, Playwright, Puppeteer, Electron, or Husky.
Installs Git dependencies, direct or transitive.
Installs remote URL dependencies, such as HTTPS tarballs.
Relies on a committed or published npm-shrinkwrap.json to pin its dependency tree.
The fastest way to check is to upgrade to npm 11.16.0 or newer and run your normal install. On npm 11, your build does not break yet: install scripts still run, and Git and remote dependencies still resolve. npm prints warnings that list exactly what will be affected under v12.
For example, an unreviewed install script produces this warning on npm 11:
npm warn allow-scripts 1 package has install scripts not yet covered by allowScripts:
npm warn allow-scripts sharp@0.33.0 (install: node install/check)
npm warn allow-scripts Run `npm approve-scripts --allow-scripts-pending` to review, or `npm approve-scripts <pkg>` to allow.
How to prepare and migrate
Work through the steps that match the warnings you saw. Each step is safe to do today on npm 11.16.0 or newer, well before your image or package reaches v12.
Step 1: Test on npm 11.16.0 or newer
Pin npm 11.16.0 or newer in your build, then run your normal install to surface the warnings.
To exercise the actual v12 failure behavior now, add --strict-allow-scripts. Unreviewed scripts then fail the install with error code ESTRICTALLOWSCRIPTS instead of warning. This is the recommended setting for continuous integration and image builds, so problems fail the build rather than being skipped silently.
Step 2: Approve the install scripts you trust (project installs)
A project install is a directory that contains a package.json. The fastest safe migration is to allow what you already have, then tighten later.
Run npm install so your dependencies are present and npm can see their scripts.
Run npm approve-scripts --allow-scripts-pending to review the list of packages with scripts. This command is read-only.
Run npm approve-scripts <pkg> to allow a package you trust, or npm approve-scripts --all to approve everything currently pending.
Block anything you do not need with npm deny-scripts <pkg>.
Commit the updated package.json. Your approvals are stored in an allowScripts map, and denials persist through future reviews.
Two details to keep in mind:
Approvals pin to the installed version unless you pass --no-allow-scripts-pin.
Order matters. npm approve-scripts <pkg> reads from your installed node_modules, so run it after a successful install. If you run it when the package is not installed, npm returns error code ENOMATCH.
Step 3: Handle global and npx installs
npm approve-scripts and npm deny-scripts only work inside a project that has a package.json. In a global or npx context they return an error, so use the allow-scripts config or flag instead. This case is common in image builds that run npm install -g <tool>.
For a single command: npm install -g --allow-scripts=<pkg,...> <tool>.
To persist the setting: npm config set allow-scripts=<pkg,...> --location=user.
Step 4: Allow the Git dependencies you rely on
Add --allow-git=all to the relevant npm install and npm ci commands.
Without it, npm v12 refuses to fetch Git dependencies and returns error code EALLOWGIT.
Use the explicit --allow-git=all form. A bare --allow-git flag is read as an invalid value and produces a config warning.
Step 5: Allow the remote URL dependencies you rely on
Add --allow-remote=all to the relevant npm install and npm ci commands.
Without it, npm v12 refuses to fetch remote dependencies and returns error code EALLOWREMOTE.
As with Git, use the explicit --allow-remote=all form rather than a bare --allow-remote flag.
Step 6: Replace npm-shrinkwrap.json
If you rely on a committed or published npm-shrinkwrap.json, that lock is ignored under v12.
For applications, rename the file to package-lock.json.
For packages you publish, use bundleDependencies if you need to ship a locked tree.
Step 7: Enforce the new defaults in CI and image builds
Set strict-allow-scripts=true in your .npmrc, or pass --strict-allow-scripts, so unreviewed scripts fail the build.
Avoid strict mode on developer machines. A new package with scripts would fail before you have a chance to review it, which slows day-to-day work.
If you currently set ignore-scripts=true, it takes precedence and no scripts run, so your allowlist does not apply. Run npm approve-scripts --allow-scripts-pending to see what would need approval, then remove ignore-scripts=true once your allowlist is in place.
Examples
Chainguard Node images
Chainguard Node images bundle npm, so they inherit npm v12 once the image updates. Update the install step in your Dockerfile to opt back into the behaviors you need.
# Before (npm 11.x): scripts run and Git and remote deps resolve automatically.
RUN npm ci
# After (npm v12): approve scripts, then allow only the resolution paths you need.
# Approvals live in the committed package.json; flags cover Git and remote deps.
RUN npm ci --strict-allow-scripts --allow-git=all --allow-remote=all
Chainguard npm package
If you install the Chainguard npm package with apk and run npm during a build or at runtime, the same steps apply. Approve scripts in your project package.json, and add --allow-git=all or --allow-remote=all to the commands that need them.
How to re-enable the old behavior (escape hatch)
If you need a build to keep working exactly as it did before v12, you can re-enable every behavior at once while you migrate properly. This is a stopgap, not a destination: it restores the automatic code-execution and resolution paths that v12 removes for security reasons.
Prefer the targeted allowlist in Step 2 and the per-command flags in Steps 4 and 5. Treat this section only as a way to buy time.
To restore the pre-v12 behavior for a single command:
npm ci --dangerously-allow-all-scripts --allow-git=all --allow-remote=all
To restore it persistently for a project or image, add this to .npmrc:
dangerously-allow-all-scripts=true
allow-git=all
allow-remote=all
Things to know:
--dangerously-allow-all-scripts runs every dependency install script with no review, which is exactly the supply-chain risk npm v12 is designed to remove. Use it only as a temporary measure, and move to an approve-scripts allowlist as soon as you can.
There is no project-wide --allow-scripts=all. In a project, --allow-scripts returns error code EALLOWSCRIPTS. Allow scripts through the allowScripts map in package.json (Step 2), or use the blanket flag above. The --allow-scripts=<pkg,...> flag is only for global and npx installs (Step 3).
npm-shrinkwrap.json cannot be re-enabled. Its support is removed in v12, so you must migrate to package-lock.json or bundleDependencies (Step 6) regardless of the flags above.
What happens if I do nothing
Once your Chainguard npm package or Chainguard Node image updates to npm v12, the four behaviors above change automatically, with no further notice:
Unapproved install scripts stop running.
Git and remote URL dependencies fail to resolve.
Any npm-shrinkwrap.json is ignored.
These changes can cause build failures or silently skipped steps, so prepare before your image or package reaches v12.
Where to get help
For Chainguard image or package questions, contact Chainguard support through your usual channel or the Chainguard support portal.
For upstream npm behavior, see the npm v12 breaking changes changelog and the npm v12 community discussion.
Comments
0 comments
Please sign in to leave a comment.