test(desktop): e2e opens a page under a CSP without 'unsafe-eval' and evaluates on it

This commit is contained in:
Abdulhakeem Mustapha
2026-11-06 19:23:00 +01:00
parent 7d146fd6f8
commit 5ca7a1afea
+50 -1
View File
@@ -213,8 +213,18 @@ async function settleDesktopStartup(page) {
}
}
const CSP_PAGE_PATH = "/csp-no-eval";
async function startTargetPage() {
const server = createServer((_request, response) => {
const server = createServer((request, response) => {
if (request.url === CSP_PAGE_PATH) {
response.writeHead(200, {
"content-type": "text/html; charset=utf-8",
"content-security-policy": "default-src 'self'; script-src 'self'",
});
response.end("<!doctype html><title>CSP page</title><h1>CSP page heading</h1>");
return;
}
response.writeHead(200, { "content-type": "text/html; charset=utf-8" });
response.end(`<!doctype html>
<html>
@@ -290,6 +300,42 @@ async function waitForGuestActiveElement(client, browserId, elementId) {
return false;
}
// A page whose Content Security Policy omits 'unsafe-eval' refuses eval(); the tools must still work.
async function verifyEvaluateOnPageWithoutUnsafeEval(client, targetUrl) {
const created = await callBrowserTool(client, "browser_new_tab", {
url: new URL(CSP_PAGE_PATH, targetUrl).href,
});
const browserId = created.browserId;
assert(typeof browserId === "string", "browser_new_tab returned no browserId for the CSP page");
try {
await callBrowserTool(client, "browser_wait", {
browserId,
text: "CSP page heading",
timeoutMs: 15_000,
});
const title = await callBrowserTool(client, "browser_evaluate", {
browserId,
function: "() => document.title",
});
assert(
JSON.parse(title.resultJson) === "CSP page",
`browser_evaluate on a page without 'unsafe-eval' returned ${title.resultJson}`,
);
// The control: the page itself really does refuse eval().
const probe = await callBrowserTool(client, "browser_evaluate", {
browserId,
function:
'() => { try { (0, eval)("1"); return "eval allowed"; } catch (error) { return error.message; } }',
});
assert(
/Content Security Policy/.test(JSON.parse(probe.resultJson)),
`The CSP page did not refuse eval(): ${probe.resultJson}`,
);
} finally {
await callBrowserTool(client, "browser_close_tab", { browserId });
}
}
async function createCallerAgent(daemonPort, workspaceId = workspaceIds[0]) {
const transport = new StreamableHTTPClientTransport(
new URL(`http://127.0.0.1:${daemonPort}/mcp/agents`),
@@ -675,6 +721,8 @@ async function runRegression({
document.body.appendChild(overlayRoot);
});
await verifyEvaluateOnPageWithoutUnsafeEval(client, targetUrl);
const created = await callBrowserTool(client, "browser_new_tab", { url: targetUrl });
const browserId = created.browserId;
assert(typeof browserId === "string", "browser_new_tab returned no browserId");
@@ -1106,6 +1154,7 @@ async function runRegression({
snapshot: "passed",
click: "passed",
localPageSelectors: "passed",
evaluateWithoutUnsafeEval: "passed",
};
}