0555937cf5da
fix: randomize Chrome web-accessible chunk URLs and assert scoped hashed Firefox resources (v5.0.82)
- time
- 2026-09-03 23:41 UTC · 1 month ago
- machine
- koh2
- agent
- claude-sonnet-4-6
- session
- PB-26-314 stable chunk URLs
- parent
- 1c0220b12de9
↓ peach-browser-0555937c.tar.gzatlas at this save
files changed5 files
manifest.firefox.json+1 −1manifest.json+1 −1package.json+1 −1scripts/web-accessible-resources.test.ts+40 −0vite.config.ts+16 −1manifest.firefox.json+1 −1
@@ -1,7 +1,7 @@11 {22 "manifest_version": 3,33 "name": "Peach Password Manager",4- "version": "5.0.81",4+ "version": "5.0.82",55 "description": "Zero-knowledge password manager",66 "browser_specific_settings": {77 "gecko": {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.81",5+ "version": "5.0.82",66 "description": "Zero-knowledge password manager",77 "action": {88 "default_popup": "src/popup/index.html",package.json+1 −1
@@ -1,6 +1,6 @@11 {22 "name": "peach",3- "version": "5.0.81",3+ "version": "5.0.82",44 "description": "Zero-knowledge password manager",55 "license": "GPL-3.0-only",66 "type": "module",scripts/web-accessible-resources.test.ts+40 −0
@@ -0,0 +1,40 @@1+import { readFileSync } from "node:fs";2+import { resolve } from "node:path";3+import { describe, expect, it } from "vitest";4+5+type WebAccessibleResource = {6+ matches: string[];7+ resources: string[];8+ use_dynamic_url?: boolean;9+};10+11+type ExtensionManifest = {12+ web_accessible_resources?: WebAccessibleResource[];13+};14+15+function readManifest(target: "chrome" | "firefox"): ExtensionManifest {16+ const directory = target === "chrome" ? "dist-chrome" : "dist-firefox";17+ return JSON.parse(18+ readFileSync(resolve(process.cwd(), directory, "manifest.json"), "utf8"),19+ ) as ExtensionManifest;20+}21+22+describe("shipped web-accessible resources", () => {23+ it("uses session-randomized URLs for Chrome content-script resources", () => {24+ const resources = readManifest("chrome").web_accessible_resources ?? [];25+26+ expect(resources).toHaveLength(1);27+ expect(resources[0]?.use_dynamic_url).toBe(true);28+ expect(resources[0]?.matches).toEqual(["<all_urls>"]);29+ expect(resources[0]?.resources.length).toBeGreaterThan(0);30+ });31+32+ it("keeps Firefox resources limited to content-script chunks with content hashes", () => {33+ const resources = readManifest("firefox").web_accessible_resources ?? [];34+ const files = resources.flatMap((entry) => entry.resources);35+36+ expect(files.length).toBeGreaterThan(0);37+ expect(files.every((file) => /^assets\/[^/]+-[A-Za-z0-9_-]+\.(?:js|css)$/.test(file))).toBe(true);38+ expect(files.every((file) => !file.includes("<dynamic_resource>"))).toBe(true);39+ });40+});vite.config.ts+16 −1
@@ -1,12 +1,19 @@11 import { defineConfig } from "vite";22 import solidPlugin from "vite-plugin-solid";33 import { crx } from "@crxjs/vite-plugin";4-import { copyFileSync, mkdirSync, readFileSync } from "fs";4+import { copyFileSync, mkdirSync, readFileSync, writeFileSync } from "fs";55 import { resolve } from "path";66 77 const target = process.env.BUILD_TARGET || "chrome";88 const manifestPath = target === "firefox" ? "./manifest.firefox.json" : "./manifest.json";99 const manifest = JSON.parse(readFileSync(manifestPath, "utf-8"));10+if (target === "chrome") {11+ manifest.web_accessible_resources = [{12+ matches: ["<all_urls>"],13+ resources: ["<dynamic_resource>"],14+ use_dynamic_url: true,15+ }];16+}1017 const passkeyE2E = process.env.PEACH_E2E_PASSKEYS === "1";1118 const outDir = target === "firefox" ? "dist-firefox" : "dist-chrome";1219 @@ -22,6 +29,14 @@2229 resolve("node_modules/pdfjs-dist/build/pdf.worker.min.mjs"),2330 resolve(outDir, "pdf.worker.min.mjs"),2431 );32+ if (target === "chrome") {33+ const outputManifest = resolve(outDir, "manifest.json");34+ const builtManifest = JSON.parse(readFileSync(outputManifest, "utf8"));35+ for (const resource of builtManifest.web_accessible_resources ?? []) {36+ resource.use_dynamic_url = true;37+ }38+ writeFileSync(outputManifest, `${JSON.stringify(builtManifest, null, 2)}\n`);39+ }2540 },2641 };2742