mirror of
https://github.com/wgtunnel/Nucleus.git
synced 2026-10-09 14:40:54 -07:00
Packaging invoked `npx --yes electron-builder@26.15.5`, which pinned only the top-level version: the ~275 transitive packages were re-resolved from the registry on every build, with no lock state to check them against and with install scripts enabled. That runs on the machine holding the code-signing certificates and notarization credentials, so a compromise anywhere in that tree executed with those. The plugin now embeds a package.json / package-lock.json pair pinning 277 packages (all from registry.npmjs.org, each with a sha512 integrity hash), stages it into a build-local directory, installs with `npm ci --ignore-scripts`, and runs the CLI directly through `node node_modules/electron-builder/cli.js`. A tarball whose bytes do not match the recorded hash now fails the build (EINTEGRITY), and no pre/postinstall hook from that tree runs at all. node and npm still come from the build machine; only the dependency tree is pinned. electron-builder's own run-time downloads (app-builder, 7-Zip, NSIS, snap/AppImage templates) remain outside any npm lock file — they are verified by its own checksums. Also in this change: - NodeJsDetector.detectNpm(), plus a shared detectSibling() helper for the nodePath override; the task now requires both node and npm and says what each is for when one is missing. - MacDmgLzma.locateAppBuilder searched the npx cache, which no longer exists, and never looked in ELECTRON_BUILDER_CACHE where electron-builder 26 actually downloads app-builder. It now checks that first, so the differential-update blockmap is no longer silently dropped after the DMG is recompressed with LZMA. - scripts/update-electron-builder-lock.sh regenerates the lock file, resolving against the public registry explicitly and refusing to run when certificate verification has been switched off — a lock file resolved over an unverified connection would record hashes for bytes nothing authenticated. - ElectronBuilderToolchainLockTest guards the boundary offline: version pinned in step with the Kotlin constant, lockfileVersion 3, every package from the public registry, every one carrying a sha512 hash. Verified end to end against a minimal consumer project (TargetFormat.Zip): the nominal path provisions the toolchain and produces the signed .app zip plus its blockmap, and tampering with a single integrity hash in the embedded lock file fails the build as intended.