Skip to content

Fix npm install on Gutenberg sites by adding SHAKE256 to Electron's Node - #588

Merged
adamziel merged 1 commit into
trunkfrom
fix/shake256-under-electron
Oct 1, 2026
Merged

adamziel merged 1 commit into
trunkfrom
fix/shake256-under-electron

Conversation

@ryanwelcher

Copy link
Copy Markdown
Collaborator

Why

Installing a new Gutenberg site fails at the npm install step with Error: Digest method not supported. Gutenberg set install-strategy = "linked" in its .npmrc (WordPress/gutenberg#83847), so npm now uses its isolated installer, which names every node_modules/.store directory with crypto.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.js gets a pure-JS SHAKE256 (FIPS 202) and provideShake256(), which routes createHash('shake256') to it only when the runtime lacks it. Every other algorithm, and plain Node, is untouched.
  • The shim preload applies it, which covers any npm/npx reached through the shims, including the Windows spawn-patch route.
  • src/install-runner.js applies 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 .store names 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.

  1. Create a new Gutenberg site.
  2. Let the npm install step run.
    • Expected: it finishes without Digest method not supported, and node_modules/.store exists in the site folder.
  3. On an existing wordpress-develop site (not linked), run npm install again.
    • Expected: it succeeds as before.

What must not have happened: the wordpress-develop install 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 on in tests/unit/npm-install.integration.test.cjs. Under npm run test:electron it fails with the old install-runner.js and passes with this change (checked). Run from the repository root.

Risks and limitations

  • Only createHash('shake256') is filled in: update() and one digest(), which is all npm uses. copy(), stream use and crypto.hash() are not, and SHA-3 is not.
  • Separate from this fix: npm 11.20 skipped the install scripts for esbuild, fsevents, nx and 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=hoisted in the child environment was a one-line alternative. Rejected because it overrides the layout Gutenberg chose on purpose, so the app's node_modules would 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.

  • Review: completed. Separate-context subagent against .github/instructions/code-review.instructions.md; npm run lint and npm test clean, npm run test:electron clean.
    • Fixed: the install-runner route had no test that would fail without the fix. Added the linked-install fixture and the integration test above.
    • Also taken: the capability probe passes outputLength, so it does not lean on Node's default output length.
    • The review also caught that the branch had first been cut from the wrong base. It was rebuilt from trunk before committing; this PR contains one commit.
  • Since review: the fixes above, re-verified with lint and both test runtimes.
Implementation notes
  • Checked against native crypto.createHash('shake256') on Node 20 for inputs and outputs on both sides of every 136-byte block boundary, with input split across update() calls: no mismatches.
  • Keccak-f[1600] works on 32-bit lane halves, because BigInt is too slow. About 40 MB/s on Electron, far beyond what npm hashes.
  • no-bitwise is disabled for the Keccak block only, with a reason.
  • Verified end to end: the real install runner on Electron 43.6.0 installs a current Gutenberg checkout (1886 .store entries).

Nothing on screen changed.

🤖 Generated with Claude Code

…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.
@coderabbitai

coderabbitai Bot commented Oct 1, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository: WordPress/contributor-toolkit/.coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 6b987118-0897-477d-964b-6fecb7fe2757

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@ryanwelcher

Copy link
Copy Markdown
Collaborator Author

@adamziel would you mind having a look here? It's a bit out of my wheel house.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@adamziel
adamziel merged commit 127ea05 into trunk Oct 1, 2026
9 checks passed
@adamziel
adamziel deleted the fix/shake256-under-electron branch October 1, 2026 15:52
@ryanwelcher ryanwelcher mentioned this pull request Oct 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

npm install fails with "Digest method not supported" on Gutenberg sites

3 participants