65263d57b9a4
fix: preserve legacy trustSource and bound sync request IDs before crypto (PB-26-111, PB-26-116, v5.0.39)
- time
- 2026-09-01 22:19 UTC · 1 month ago
- machine
- koh2
- agent
- claude-opus-5
- session
- 2026-09-01 security assessment remediation
- parent
- 6dfff89fba08
↓ peach-browser-65263d57.tar.gzatlas at this save
files changed6 files
manifest.firefox.json+1 −1manifest.json+1 −1package.json+1 −1src/background/sync-coordinator.ts+6 −0src/background/sync-vault-adapter.ts+1 −1src/shared/sync-limits.ts+3 −1manifest.firefox.json+1 −1
@@ -1,7 +1,7 @@11 {22 "manifest_version": 3,33 "name": "Peach Password Manager",4- "version": "5.0.38",4+ "version": "5.0.39",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.38",5+ "version": "5.0.39",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.38",3+ "version": "5.0.39",44 "description": "Zero-knowledge password manager",55 "license": "GPL-3.0-only",66 "type": "module",src/background/sync-coordinator.ts+6 −0
@@ -214,6 +214,9 @@214214 if (requestIn.type !== "SYNC_REQUEST") {215215 return errorOutcome(result, `expected SYNC_REQUEST, got ${requestIn.type}`);216216 }217+ if (requestIn.entryIds.length > SYNC_LIMITS.MAX_REQUEST_ENTRY_COUNT) {218+ return errorOutcome(result, "sync request entry count exceeds limit");219+ }217220 // Sanity: the peer's request must be a subset of what its manifest218221 // declared as newer. A malformed/over-eager request is a protocol219222 // violation but not a data-safety problem — we just send what they ask.@@ -405,6 +408,9 @@405408 const requestIn = await receiveMessage(session, timer);406409 if (requestIn.type !== "SYNC_REQUEST") {407410 return errorOutcome(result, `expected SYNC_REQUEST, got ${requestIn.type}`);411+ }412+ if (requestIn.entryIds.length > SYNC_LIMITS.MAX_REQUEST_ENTRY_COUNT) {413+ return errorOutcome(result, "sync request entry count exceeds limit");408414 }409415 const wantFromPeer = diffNewer(manifestIn.entries, ourEntries);410416 await sendMessage(session, { type: "SYNC_REQUEST", entryIds: wantFromPeer });src/background/sync-vault-adapter.ts+1 −1
@@ -471,7 +471,7 @@471471 longTermPublicKeyHex: entry.longTermPublicKeyHex.toLowerCase(),472472 signingPublicKeyHex: entry.signingPublicKeyHex.toLowerCase(),473473 pairedAt: existing.pairedAt ?? entry.pairedAt,474- trustSource: existing.trustSource ?? "direct",474+ trustSource: existing.trustSource,475475 wsPort: existing.wsPort ?? entry.wsPort,476476 rendezvousSecretHex:477477 existing.trustSource === "vouched" && meshRoutesrc/shared/sync-limits.ts+3 −1
@@ -75,8 +75,10 @@7575 * above 32 MiB; 24 MiB leaves transport overhead and platform margin.7676 */7777 MAX_FRAME_BYTES: 24 * 1024 * 1024, // 24 MiB78- /** Max entries accepted in one SYNC_ENTRIES / manifest payload. */78+ /** Max entries accepted in one SYNC_ENTRIES / manifest / request payload. */7979 MAX_ENTRY_COUNT: 100_000,80+ /** Max IDs a peer may request before per-entry crypto work begins. */81+ MAX_REQUEST_ENTRY_COUNT: 100_000,8082 /** Max plaintext size of one decrypted entry envelope. */8183 MAX_ENTRY_PLAINTEXT_BYTES: 512 * 1024, // 512 KiB8284 /** Max tombstones accepted in one SYNC_TOMBSTONES payload. */