fix(browser): drop disallowed redirect evidence

This commit is contained in:
morluto 2026-07-14 05:12:40 +00:00
parent 7d5621dfbc
commit 8481be9c97
3 changed files with 43 additions and 7 deletions

View File

@ -139,13 +139,11 @@ export class CdpCaptureEvents {
const requestId = stringValue(params.requestId);
const request = recordValue(params.request);
const sanitized = allowedSanitizedUrl(request?.url, this.allowedOrigins);
if (
requestId === undefined ||
requestId.length > 256 ||
request === undefined ||
sanitized === undefined
)
if (requestId === undefined || requestId.length > 256) return;
if (request === undefined || sanitized === undefined) {
this.network.delete(requestId);
return;
}
if (
this.network.size >= this.input.limits.max_network_events &&
!this.network.has(requestId)
@ -181,7 +179,12 @@ export class CdpCaptureEvents {
if (requestId === undefined || requestId.length > 256) return;
const current = this.network.get(requestId);
const response = recordValue(params.response);
if (current === undefined || response === undefined) return;
const sanitized = allowedSanitizedUrl(response?.url, this.allowedOrigins);
if (current === undefined) return;
if (response === undefined || sanitized === undefined) {
this.network.delete(requestId);
return;
}
this.network.set(requestId, {
...current,
status: numberValue(response.status) ?? null,

View File

@ -127,6 +127,25 @@ describe("CdpBrowserProvider", () => {
expect(methods).not.toContain("Runtime.evaluate");
});
it("drops network evidence when a request redirects outside the approved origin", async () => {
const browser = await startFakeCdpBrowser({
redirectToDisallowedOrigin: true,
});
browsers.push(browser);
const result = await new CdpBrowserProvider().inspectPage(
inspectWebPageInputSchema.parse({
cdp_endpoint: browser.endpoint,
allowed_origins: [browser.allowedOrigin],
target_id: "allowed-page",
approved: true,
observation_ms: 0,
}),
);
if (!result.ok) throw result.error;
expect(result.value.network.requests).toEqual([]);
});
it("includes allowed script source only after explicit approval", async () => {
const browser = await startFakeCdpBrowser();
browsers.push(browser);

View File

@ -33,6 +33,7 @@ interface FakeOptions {
readonly navigateDuringCaptureUrl?: string;
readonly extraCollections?: boolean;
readonly foreignSessionEvents?: boolean;
readonly redirectToDisallowedOrigin?: boolean;
}
/** Start a real HTTP/WebSocket fake at the same seams as a user-owned browser. */
@ -487,9 +488,22 @@ const emitEvents = (
],
},
});
if (options.redirectToDisallowedOrigin === true)
event(socket, "Network.requestWillBeSent", command.sessionId, {
requestId: "request-1",
type: "Fetch",
request: {
url: "https://private.example.test/redirected",
method: "GET",
},
});
event(socket, "Network.responseReceived", command.sessionId, {
requestId: "request-1",
response: {
url:
options.redirectToDisallowedOrigin === true
? "https://private.example.test/redirected"
: url,
status: 200,
mimeType: "application/json",
headers: { "Set-Cookie": "response-secret" },