Repository navigation
Fix npm install on Gutenberg sites by adding SHAKE256 to Electron's Node - #588
Conversation
…586 Gutenberg set `install-strategy = linked` (WordPress/gutenberg#83847), which sends npm through its isolated installer. That names node_modules/.store with crypto.createHash('shake256'), and Electron's BoringSSL has no SHAKE256, so `npm install` failed with "Digest method not supported" before writing anything. electron-node-compat.js now carries a pure-JS SHAKE256 and routes createHash('shake256') to it only when the runtime lacks one. The shim preload applies it, and the install runner, which loads npm without the preload, applies it before requiring npm.
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository: WordPress/contributor-toolkit/.coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@adamziel would you mind having a look here? It's a bit out of my wheel house. |
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
No unresolved correctness, architecture, security, performance, cross-platform, or test-coverage issues were found.
Review effort: Balanced
Findings: None
What changed in this PR
Adds SHAKE256 compatibility to Electron’s Node runtime so Gutenberg’s linked npm installs succeed.
Changes:
- Implements and conditionally enables SHAKE256.
- Applies compatibility to npm runner and shimmed child processes.
- Adds hash-vector, runtime, and linked-install tests.
| File | Description |
|---|---|
src/electron-node-compat.js |
Implements and provides SHAKE256 compatibility. |
src/install-runner.js |
Enables SHAKE256 before loading npm. |
tests/unit/electron-node-compat.test.cjs |
Tests hash correctness and compatibility wiring. |
tests/unit/npm-install.integration.test.cjs |
Tests linked npm installation end to end. |
tests/unit/fixtures/linked-install/.npmrc |
Enables linked install strategy. |
tests/unit/fixtures/linked-install/package.json |
Defines the linked-install fixture. |
tests/unit/fixtures/linked-install/local-dep/package.json |
Provides its offline local dependency. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Why
Installing a new Gutenberg site fails at the npm install step with
Error: Digest method not supported. Gutenberg setinstall-strategy = "linked"in its.npmrc(WordPress/gutenberg#83847), so npm now uses its isolated installer, which names everynode_modules/.storedirectory withcrypto.createHash('shake256'). The app runs npm on Electron's Node, whose BoringSSL has no SHAKE256, so the install throws before it writes anything.What changes
src/electron-node-compat.jsgets a pure-JS SHAKE256 (FIPS 202) andprovideShake256(), which routescreateHash('shake256')to it only when the runtime lacks it. Every other algorithm, and plain Node, is untouched.npm/npxreached through the shims, including the Windows spawn-patch route.src/install-runner.jsapplies it before requiring npm. This is the route the bug hit: the runner loads npm in-process and never gets the preload.It is the real hash, not a stand-in, so the
.storenames match what a contributor gets on plain Node.How to test this
Platforms: any. Build: the Buildkite artifact for the current head.
Starting state: no Gutenberg site in the app.
Digest method not supported, andnode_modules/.storeexists in the site folder.wordpress-developsite (not linked), run npm install again.What must not have happened: the
wordpress-developinstall changing behaviour. It does not use the linked strategy, so it never asks for SHAKE256.Covered by
a linked install succeeds on the runtime the app runs npm onintests/unit/npm-install.integration.test.cjs. Undernpm run test:electronit fails with the oldinstall-runner.jsand passes with this change (checked). Run from the repository root.Risks and limitations
createHash('shake256')is filled in:update()and onedigest(), which is all npm uses.copy(), stream use andcrypto.hash()are not, and SHA-3 is not.esbuild,fsevents,nxand others on a full Gutenberg install (npm install-scripts approve). Not investigated here.Related
Fixes #586
Design decisions and alternatives considered
Forcing
npm_config_install_strategy=hoistedin the child environment was a one-line alternative. Rejected because it overrides the layout Gutenberg chose on purpose, so the app'snode_moduleswould differ from Gutenberg's CI.The hash is applied only after probing the runtime, so a future Electron that gains SHAKE256 uses its own.
Review outcome (required, see AGENTS.md)
1 [fix here] · 0 [follow-up]: fixed.
.github/instructions/code-review.instructions.md;npm run lintandnpm testclean,npm run test:electronclean.linked-installfixture and the integration test above.outputLength, so it does not lean on Node's default output length.trunkbefore committing; this PR contains one commit.Implementation notes
crypto.createHash('shake256')on Node 20 for inputs and outputs on both sides of every 136-byte block boundary, with input split acrossupdate()calls: no mismatches.no-bitwiseis disabled for the Keccak block only, with a reason..storeentries).Nothing on screen changed.
🤖 Generated with Claude Code