af7feb6fddaf

minimize page GET_SETTINGS to theme accent and attested summon record (v5.0.71)

time
2026-09-03 21:58 UTC · 1 month ago
machine
koh2
agent
claude-sonnet-4-6
session
PB-26-303 settings disclosure
parent
db62c59f8b55
5 files manifest.firefox.json+1 −1manifest.json+1 −1package.json+1 −1src/background/messages.test.ts+44 −0src/background/messages.ts+15 −2
manifest.firefox.json+1 −1
@@ -1,7 +1,7 @@11 {22   "manifest_version": 3,33   "name": "Peach Password Manager",4-  "version": "5.0.70",4+  "version": "5.0.71",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.70",5+  "version": "5.0.71",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.70",3+  "version": "5.0.71",44   "description": "Zero-knowledge password manager",55   "license": "GPL-3.0-only",66   "type": "module",

view file

src/background/messages.test.ts+44 −0
@@ -154,6 +154,50 @@154154     });155155   }156156 157+  it("PB-26-303: page GET_SETTINGS returns only theme, accent, and its own summon record", async () => {158+    storage.peach_settings = {159+      theme: "dark",160+      accentColor: "peach",161+      autoLockMinutes: 5,162+      pinEnabled: true,163+      manualSummonDomains: {164+        "example.com": { firstSummonedAt: 1, summonCount: 2, lastSummonedAt: 3 },165+        "other.example": { firstSummonedAt: 4, summonCount: 5, lastSummonedAt: 6 },166+      },167+    };168+    const response = await dispatch(169+      { type: "GET_SETTINGS" },170+      {171+        id: "peach-extension",172+        url: "https://login.example.com/form",173+        tab: { id: 1 },174+        frameId: 0,175+      } as chrome.runtime.MessageSender,176+    );177+178+    expect(response).toEqual({179+      ok: true,180+      data: {181+        theme: "dark",182+        accentColor: "peach",183+        manualSummonDomains: {184+          "example.com": { firstSummonedAt: 1, summonCount: 2, lastSummonedAt: 3 },185+        },186+      },187+    });188+    await expect(dispatch({ type: "GET_SETTINGS" })).resolves.toMatchObject({189+      ok: true,190+      data: {191+        autoLockMinutes: 5,192+        pinEnabled: true,193+        manualSummonDomains: {194+          "example.com": expect.anything(),195+          "other.example": expect.anything(),196+        },197+      },198+    });199+  });200+157201   it("GET_ENTRIES when unlocked returns the entry array", async () => {158202     const vault = await import("./vault");159203     await vault.createVault("correct-pass-12345");

view file

src/background/messages.ts+15 −2
@@ -1002,8 +1002,21 @@10021002         }10031003         return { ok: true, data: results };10041004       }1005-      case "GET_SETTINGS":1006-        return { ok: true, data: await vault.ensureSettingsLoaded() };1005+      case "GET_SETTINGS": {1006+        const settings = await vault.ensureSettingsLoaded();1007+        if (!isPageSender(sender)) return { ok: true, data: settings };1008+1009+        const safeSettings: Pick<vault.VaultSettings, "accentColor" | "theme"> & {1010+          manualSummonDomains?: NonNullable<vault.VaultSettings["manualSummonDomains"]>;1011+        } = {1012+          accentColor: settings.accentColor,1013+          theme: settings.theme,1014+        };1015+        const domain = attestedSenderDomain(sender);1016+        const ownSummon = domain ? settings.manualSummonDomains?.[domain] : undefined;1017+        if (domain && ownSummon) safeSettings.manualSummonDomains = { [domain]: ownSummon };1018+        return { ok: true, data: safeSettings };1019+      }10071020       case "UPDATE_SETTINGS": {10081021         const patch = msg.payload;10091022         if (!patch || typeof patch !== "object" || Array.isArray(patch)) {

view file