a3e298dd0300
L16/SEC-010: validate incoming license signature before storing in applyIncomingVault
- time
- 2026-05-16 05:48 UTC · 5 months ago
- machine
- koh2
- parent
- 987a154bae24
↓ peach-browser-a3e298dd.tar.gzatlas at this save
files changed2 files
src/background/sync.adversarial.test.ts+6 −2src/background/vault.ts+9 −1src/background/sync.adversarial.test.ts+6 −2
@@ -252,7 +252,11 @@252252 expect(storage.peach_license).toBe("my-existing-license");253253 });254254 255- it("no local license: incoming license is adopted", async () => {255+ it("no local license: invalid incoming license is rejected (L16/SEC-010)", async () => {256+ // L16 hardens applyIncomingVault to validate the signature before257+ // adopting. Without a real signed license fixture, an unsigned string258+ // must be silently dropped — a peer cannot plant arbitrary text as259+ // our peach_license.256260 const vault = await setupBlobs();257261 delete storage.peach_license;258262 await vault.applyIncomingVault(@@ -260,7 +264,7 @@260264 Date.now() + 100_000,261265 "incoming-license"262266 );263- expect(storage.peach_license).toBe("incoming-license");267+ expect(storage.peach_license).toBeUndefined();264268 });265269 266270 it("no incoming license: local license is unchanged", async () => {src/background/vault.ts+9 −1
@@ -2269,7 +2269,15 @@22692269 const licenseRaw = await chrome.storage.local.get('peach_license');22702270 const existing = (licenseRaw as Record<string, unknown>)['peach_license'];22712271 if (!existing) {2272- await chrome.storage.local.set({ peach_license: remoteLicense });2272+ // L16/SEC-010: validate signature before storing. An unverified peer2273+ // could otherwise plant an arbitrary string as the local license and2274+ // poison the next isProUser() / activateLicense() check.2275+ const { validateLicense } = await import('./license');2276+ const validation = await validateLicense(remoteLicense);2277+ if (validation.valid) {2278+ await chrome.storage.local.set({ peach_license: remoteLicense });2279+ }2280+ // Silently ignore invalid — never store garbage.22732281 }22742282 }22752283