Windows smoke: foreign-page mic check on a local origin (#19) #31

Merged
jared merged 1 commits from smoke-foreign-origin into main 2026-09-30 12:46:31 -04:00
+25 -7
View File
@@ -11,6 +11,7 @@
// instead of failing, so the same script runs on main and on PR branches. // instead of failing, so the same script runs on main and on PR branches.
import { writeFileSync, mkdirSync } from 'node:fs'; import { writeFileSync, mkdirSync } from 'node:fs';
import { execSync } from 'node:child_process'; import { execSync } from 'node:child_process';
import { createServer } from 'node:http';
import { chromium } from 'playwright-core'; import { chromium } from 'playwright-core';
const OUT = process.argv[2] || 'smoke-out'; const OUT = process.argv[2] || 'smoke-out';
@@ -150,8 +151,19 @@ else if (!kc.supported) record('keychain round trip', 'fail', 'secure_session_su
else record('keychain round trip', kc.roundTrip && kc.restored ? 'pass' : 'fail', JSON.stringify(kc)); else record('keychain round trip', kc.roundTrip && kc.restored ? 'pass' : 'fail', JSON.stringify(kc));
// 7. A foreign page loaded in the window must not get the microphone (#22). // 7. A foreign page loaded in the window must not get the microphone (#22).
await page.goto('https://example.com/').catch(() => undefined); // Served locally on another port (a different origin, still a secure context),
const foreignMic = await page.evaluate(async () => { // so the check doesn't depend on the runner reaching the internet.
const foreign = createServer((_, res) => {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end('<!doctype html><title>foreign</title>foreign page');
});
await new Promise((r) => foreign.listen(9333, '127.0.0.1', r));
const FOREIGN = 'http://localhost:9333/';
await page.goto(FOREIGN).catch(() => undefined);
if (!page.url().startsWith(FOREIGN)) {
record('microphone refused to a foreign page', 'fail', `navigation did not happen (at ${page.url()})`);
} else {
const foreignMic = await page.evaluate(async () => {
try { try {
const s = await navigator.mediaDevices.getUserMedia({ audio: true }); const s = await navigator.mediaDevices.getUserMedia({ audio: true });
s.getTracks().forEach((t) => t.stop()); s.getTracks().forEach((t) => t.stop());
@@ -159,12 +171,18 @@ const foreignMic = await page.evaluate(async () => {
} catch (e) { } catch (e) {
return e.name; return e.name;
} }
}); });
record( const guarded = cfg.desktopCallOrigin !== undefined; // builds with #22 also carry #43
let status = 'info';
if (foreignMic === 'NotAllowedError') status = 'pass';
else if (guarded) status = 'fail';
record(
'microphone refused to a foreign page', 'microphone refused to a foreign page',
foreignMic === 'NotAllowedError' ? 'pass' : 'info', status,
`${foreignMic}${foreignMic === 'ok' ? ' (build without the #22 origin check)' : ''}`, `${foreignMic} at ${page.url()}${status === 'info' ? ' (build without the #22 origin check)' : ''}`,
); );
}
foreign.close();
await page.goto(APP).catch(() => undefined); await page.goto(APP).catch(() => undefined);
await page.screenshot({ path: `${OUT}/02-end.png` }).catch(() => undefined); await page.screenshot({ path: `${OUT}/02-end.png` }).catch(() => undefined);