72b453994169
fix: SEC-002/THREAT-003 delete TEST handlers (v2.45.2)
- time
- 2026-05-15 20:55 UTC · 5 months ago
- machine
- koh2
- parent
- 5c4a71d3e83b
↓ peach-browser-72b45399.tar.gzatlas at this save
files changed6 files
manifest.firefox.json+1 −1manifest.json+1 −1package.json+1 −1src/background/messages.ts+0 −120src/content/passkeys-firefox-relay.test.ts+2 −2src/shared/types.ts+0 −5manifest.firefox.json+1 −1
@@ -1,7 +1,7 @@11 {22 "manifest_version": 3,33 "name": "Peach",4- "version": "2.45.1",4+ "version": "2.45.2",55 "description": "Zero-knowledge password manager",66 "browser_specific_settings": {77 "gecko": {manifest.json+1 −1
@@ -1,7 +1,7 @@11 {22 "manifest_version": 3,33 "name": "Peach",4- "version": "2.45.1",4+ "version": "2.45.2",55 "description": "Zero-knowledge password manager",66 "action": {77 "default_popup": "src/popup/index.html",package.json+1 −1
@@ -1,6 +1,6 @@11 {22 "name": "peach",3- "version": "2.45.1",3+ "version": "2.45.2",44 "description": "Zero-knowledge password manager",55 "type": "module",66 "scripts": {src/background/messages.ts+0 −120
@@ -1337,126 +1337,6 @@13371337 await publishInMemoryVault(entries);13381338 return { ok: true };13391339 }1340- // --- PNA compatibility test handlers — REMOVE BEFORE RELEASE ---1341- case "TEST_LOCAL_WEBSOCKET": {1342- const { ip } = (msg.payload ?? {}) as { ip?: string };1343- if (!ip) return { ok: false, error: "ip required" };1344- return new Promise((resolve) => {1345- try {1346- const ws = new WebSocket(`ws://${ip}:44100`);1347- ws.onopen = () => { ws.close(); resolve({ ok: true, data: { connected: true } }); };1348- ws.onerror = () => resolve({ ok: false, error: "connection_failed" });1349- setTimeout(() => { ws.close(); resolve({ ok: false, error: "timeout" }); }, 3000);1350- } catch (err) {1351- resolve({ ok: false, error: String(err) });1352- }1353- });1354- }1355- case "TEST_SUBNET_DETECTION": {1356- const subnet = await getLocalSubnet();1357- return { ok: true, data: { subnet } };1358- }1359- case "TEST_SUBNET_SCAN": {1360- const subnet = await getLocalSubnet();1361- if (!subnet) return { ok: false, error: "no_subnet" };1362- const start = Date.now();1363- const result = await discoverDevice(subnet, "000000000000000000000000000000000000000000000000000000000000000000");1364- return { ok: true, data: { elapsed: Date.now() - start, found: !!result } };1365- }1366- case 'TEST_WS_LOCAL': {1367- const { ip } = msg.payload as { ip: string };1368-1369- return new Promise((resolve) => {1370- const log: string[] = [];1371- log.push(`Attempting ws://${ip}:44100 from service worker...`);1372-1373- let ws: WebSocket;1374- let settled = false;1375- const settle = (result: MessageResponse) => {1376- if (!settled) { settled = true; resolve(result); }1377- };1378-1379- try {1380- ws = new WebSocket(`ws://${ip}:44100`);1381-1382- ws.onopen = () => {1383- log.push('SUCCESS: WebSocket connected');1384- ws.close();1385- settle({ ok: true, data: { log } });1386- };1387-1388- ws.onerror = (e) => {1389- log.push(`FAILED: onerror fired — ${String(e)}`);1390- settle({ ok: false, error: 'ws_error', data: { log } });1391- };1392-1393- ws.onclose = (e) => {1394- if (e.code !== 1000) {1395- log.push(`CLOSED unexpectedly: code=${e.code} reason=${e.reason}`);1396- settle({ ok: false, error: 'ws_closed', data: { code: e.code, log } });1397- }1398- };1399-1400- setTimeout(() => {1401- try { ws.close(); } catch {}1402- log.push('FAILED: 5 second timeout — connection never opened');1403- settle({ ok: false, error: 'timeout', data: { log } });1404- }, 5000);1405-1406- } catch (err) {1407- log.push(`FAILED: WebSocket constructor threw — ${String(err)}`);1408- settle({ ok: false, error: 'constructor_threw', data: { log } });1409- }1410- });1411- }1412-1413- case 'TEST_SUBNET_DETECT': {1414- return new Promise((resolve) => {1415- try {1416- // RTCPeerConnection availability varies by context — this is what we're testing1417- // eslint-disable-next-line @typescript-eslint/no-explicit-any1418- const RTC = (globalThis as any).RTCPeerConnection as (new (cfg: object) => RTCPeerConnection) | undefined;1419- if (!RTC) {1420- resolve({ ok: false, error: 'RTCPeerConnection is not defined' });1421- return;1422- }1423- const pc = new RTC({ iceServers: [] });1424- pc.createDataChannel('');1425- pc.createOffer().then((o) => pc.setLocalDescription(o));1426-1427- const candidates: string[] = [];1428- const timer = setTimeout(() => {1429- pc.close();1430- if (candidates.length === 0) {1431- resolve({ ok: false, error: 'no_candidates', data: { candidates } });1432- } else {1433- const subnet = candidates[0].match(/(\d+\.\d+\.\d+)\.\d+/)?.[1];1434- resolve({ ok: true, data: { subnet, candidates } });1435- }1436- }, 2000);1437-1438- pc.onicecandidate = (e) => {1439- if (!e.candidate) return;1440- const m = e.candidate.candidate.match(/(\d+\.\d+\.\d+\.\d+)/);1441- if (m && !m[1].startsWith('127')) candidates.push(m[1]);1442- };1443-1444- pc.onicegatheringstatechange = () => {1445- if (pc.iceGatheringState === 'complete') {1446- clearTimeout(timer);1447- pc.close();1448- const subnet = candidates[0]?.match(/(\d+\.\d+\.\d+)\.\d+/)?.[1];1449- resolve({ ok: candidates.length > 0, data: { subnet, candidates } });1450- }1451- };1452- } catch (err) {1453- resolve({ ok: false, error: String(err) });1454- }1455- });1456- }1457-1458- // --- end test handlers ---1459-14601340 case "ML_INIT":14611341 return { ok: true };14621342 src/content/passkeys-firefox-relay.test.ts+2 −2
@@ -61,8 +61,8 @@6161 "GET_IDENTITIES",6262 "SEARCH_VAULT",6363 "GET_ENTRY_FOR_FILL",64- "TEST_LOCAL_WEBSOCKET",65- "TEST_WS_LOCAL",64+ "LOCAL_WEBSOCKET_PROBE",65+ "SUBNET_DETECT_PROBE",6666 "",6767 "TOTALLY_MADE_UP",6868 ];src/shared/types.ts+0 −5
@@ -306,11 +306,6 @@306306 | "GET_IDENTITY_SUGGESTIONS"307307 | "TOUCH_AUTO_LOCK"308308 | "POPULATE_INLINE_VAULT"309- | "TEST_LOCAL_WEBSOCKET"310- | "TEST_SUBNET_DETECTION"311- | "TEST_SUBNET_SCAN"312- | "TEST_WS_LOCAL"313- | "TEST_SUBNET_DETECT"314309 | "SAVE_NOTE"315310 | "DELETE_NOTE"316311 | "GET_NOTES"