06ca6237835c

fix: add Noise WASM provenance gate to CI (PB-26-003) — scripts/check-noise-core.mjs rebuilds the blob from crypto-core and fails on drift from the committed artifacts, wired into scripts/ci.ts after Tests; gate verified green with deterministic rebuild matching committed SHA; bump 5.0.2→5.0.3

time
2026-08-29 23:57 UTC · 1 month ago
machine
koh2
agent
glm-5.3-flash
session
pb-26 audit fixes
parent
5b7714bd29dd
5 files manifest.firefox.json+1 −1manifest.json+1 −1package.json+1 −1scripts/check-noise-core.mjs+47 −0scripts/ci.ts+6 −0
manifest.firefox.json+1 −1
@@ -1,7 +1,7 @@11 {22   "manifest_version": 3,33   "name": "Peach Password Manager",4-  "version": "5.0.2",4+  "version": "5.0.3",55   "description": "Zero-knowledge password manager",66   "browser_specific_settings": {77     "gecko": {

view file

manifest.json+1 −1
@@ -2,7 +2,7 @@22   "manifest_version": 3,33   "minimum_chrome_version": "116",44   "name": "Peach Password Manager",5-  "version": "5.0.2",5+  "version": "5.0.3",66   "description": "Zero-knowledge password manager",77   "action": {88     "default_popup": "src/popup/index.html",

view file

package.json+1 −1
@@ -1,6 +1,6 @@11 {22   "name": "peach",3-  "version": "5.0.2",3+  "version": "5.0.3",44   "description": "Zero-knowledge password manager",55   "license": "GPL-3.0-only",66   "type": "module",

view file

scripts/check-noise-core.mjs+47 −0
@@ -0,0 +1,47 @@1+// PB-26-003: verify the committed Noise WASM still matches crypto-core source.2+// Rebuilds via npm run build:noise-core and fails if any shipped artifact3+// drifts, so "reviewed source → shipped binary" is machine-enforced.4+import { spawnSync } from "node:child_process";5+import { createHash } from "node:crypto";6+import { readFileSync } from "node:fs";7+import { dirname, resolve } from "node:path";8+import { fileURLToPath } from "node:url";9+10+const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");11+const dest = resolve(root, "src/shared/noise-core-wasm");12+const files = [13+  "peach_noise_core.js",14+  "peach_noise_core.d.ts",15+  "peach_noise_core_bg.wasm",16+  "peach_noise_core_bg.wasm.d.ts",17+  "peach_noise_core_bytes.ts",18+];19+20+function hashTree() {21+  return Object.fromEntries(22+    files.map((f) => [23+      f,24+      createHash("sha256").update(readFileSync(resolve(dest, f))).digest("hex"),25+    ]),26+  );27+}28+29+const before = hashTree();30+const build = spawnSync("npm", ["run", "build:noise-core"], { stdio: "inherit" });31+if (build.status !== 0) {32+  console.error(33+    "noise-core rebuild failed — committed WASM provenance cannot be verified (PB-26-003)",34+  );35+  process.exit(build.status ?? 1);36+}37+38+const after = hashTree();39+const drifted = files.filter((f) => before[f] !== after[f]);40+if (drifted.length > 0) {41+  console.error(42+    `committed Noise WASM does not match crypto-core/src/lib.rs — drifted: ${drifted.join(", ")}\n` +43+      "run `npm run build:noise-core` and commit the regenerated files",44+  );45+  process.exit(1);46+}47+console.log("committed Noise WASM matches crypto-core source");

view file

scripts/ci.ts+6 −0
@@ -40,6 +40,12 @@4040     cmd: ['npm', 'test', '--', '--reporter=verbose'],4141   },4242   {43+    // PB-26-003: rebuild the Noise WASM from crypto-core and fail if the44+    // committed blob drifts — "reviewed source → shipped binary" enforced.45+    name: 'Noise WASM provenance',46+    cmd: ['node', 'scripts/check-noise-core.mjs'],47+  },48+  {4349     name: 'Chrome build',4450     cmd: ['npm', 'run', 'build:chrome'],4551   },

view file