What happened
The root package.json declares:
"allowScripts": {
"esbuild@0.27.7": true,
"@jackwener/opencli@1.8.4": true,
"node-pty@1.2.0-beta.15": true
}
npm matches these by exact name@version. Our lockfile installs esbuild@0.28.2 and @jackwener/opencli@1.8.6, so two of the three entries match nothing and only the node-pty entry is still live.
Because the field is present, npm denies by default, so a clean npm ci from the repo root silently skips eight packages' install scripts and still exits 0:
npm warn install-scripts 8 packages have install scripts not yet covered by allowScripts:
npm warn install-scripts @astryxdesign/cli@0.4.5 (postinstall: node scripts/postinstall.mjs)
npm warn install-scripts @astryxdesign/core@0.5.0 (postinstall: node scripts/postinstall.mjs)
npm warn install-scripts @jackwener/opencli@1.8.6 (postinstall: node scripts/postinstall.js || true; node scripts/fetch-adapters.js || true)
npm warn install-scripts electron-winstaller@5.4.0 (install: node ./script/select-7z-arch.js)
npm warn install-scripts esbuild@0.28.2 (postinstall: node install.js)
npm warn install-scripts fsevents@2.3.3 (install: (install scripts present))
npm warn install-scripts fsevents@2.3.2 (install: (install scripts present))
npm warn install-scripts protobufjs@7.6.5 (postinstall: node scripts/postinstall)
The defect is not any individual skip. It is that a version-pinned allowlist goes stale on every dependency bump, silently, and we can no longer tell "reviewed and allowed" apart from "no longer matches anything". We chose deny-by-default deliberately; right now that choice is not being enforced the way the file suggests.
How to reproduce
Run npm ci from the repo root on a clean checkout and read the install-scripts warnings.
Environment
macOS arm64, Node 24, npm 11.19.0.
Additional context
This splits into a part that is confirmed and a part that still needs investigation. The two can land as one change or two — whichever the person picking it up prefers.
Confirmed, and safe to act on:
- The allowlist has rotted and will rot again on the next bump of any listed package.
- It needs a guard. Please check first whether npm 11 supports anything other than exact
name@version keys; if it does not, a check script is the only way to keep the list honest. There is an existing family of check:* scripts in the root package.json, wired through .github/workflows/ci.yml — extending that seam is preferable to inventing a new mechanism.
Still open, and the reason I have not proposed a specific list:
- Whether skipping each of the eight actually degrades anything on macOS arm64, Linux x64 or Windows x64. Please verify rather than assume. For example
esbuild ships its binary through the @esbuild/<platform> optional dependency, which may make its install.js redundant; the two @astryxdesign postinstalls appeared to only print a "Next step: run npx @astryxdesign/cli init" notice; electron-winstaller matters only on the Windows packaging lane. Recording the evidence per package matters more than the final verdict, because the next person will otherwise have to redo it.
Deny-by-default should stay. The goal is an honest list, not allowing all eight — where a skip is harmless, saying so explicitly is a better outcome than adding it.
One thing that is out of scope: npm mentions an .npmrc allow-scripts setting in its first warning line. This repository has no .npmrc; that setting comes from the individual contributor's own ~/.npmrc and is unrelated.
Separately, and also out of scope: I have seen worktrees where node_modules/electron/ exists but dist/ and path.txt do not, and where the patches/ entry for @ai-sdk/provider-utils was not applied either. That points at the root postinstall chain not running at all, which is a different failure — Electron's binary is fetched by scripts/install-electron-with-retry.mjs, not by any allowlisted dependency script. I could not determine the cause and am not filing it until I can.
Analysis produced with Claude Code.
What happened
The root
package.jsondeclares:npm matches these by exact
name@version. Our lockfile installsesbuild@0.28.2and@jackwener/opencli@1.8.6, so two of the three entries match nothing and only thenode-ptyentry is still live.Because the field is present, npm denies by default, so a clean
npm cifrom the repo root silently skips eight packages' install scripts and still exits 0:The defect is not any individual skip. It is that a version-pinned allowlist goes stale on every dependency bump, silently, and we can no longer tell "reviewed and allowed" apart from "no longer matches anything". We chose deny-by-default deliberately; right now that choice is not being enforced the way the file suggests.
How to reproduce
Run
npm cifrom the repo root on a clean checkout and read theinstall-scriptswarnings.Environment
macOS arm64, Node 24, npm 11.19.0.
Additional context
This splits into a part that is confirmed and a part that still needs investigation. The two can land as one change or two — whichever the person picking it up prefers.
Confirmed, and safe to act on:
name@versionkeys; if it does not, a check script is the only way to keep the list honest. There is an existing family ofcheck:*scripts in the rootpackage.json, wired through.github/workflows/ci.yml— extending that seam is preferable to inventing a new mechanism.Still open, and the reason I have not proposed a specific list:
esbuildships its binary through the@esbuild/<platform>optional dependency, which may make itsinstall.jsredundant; the two@astryxdesignpostinstalls appeared to only print a "Next step: run npx @astryxdesign/cli init" notice;electron-winstallermatters only on the Windows packaging lane. Recording the evidence per package matters more than the final verdict, because the next person will otherwise have to redo it.Deny-by-default should stay. The goal is an honest list, not allowing all eight — where a skip is harmless, saying so explicitly is a better outcome than adding it.
One thing that is out of scope: npm mentions an
.npmrcallow-scriptssetting in its first warning line. This repository has no.npmrc; that setting comes from the individual contributor's own~/.npmrcand is unrelated.Separately, and also out of scope: I have seen worktrees where
node_modules/electron/exists butdist/andpath.txtdo not, and where thepatches/entry for@ai-sdk/provider-utilswas not applied either. That points at the rootpostinstallchain not running at all, which is a different failure — Electron's binary is fetched byscripts/install-electron-with-retry.mjs, not by any allowlisted dependency script. I could not determine the cause and am not filing it until I can.Analysis produced with Claude Code.