Net: strip sensitive headers on cross-origin redirects

This commit is contained in:
Andrii Furmanets
2026-02-18 21:22:42 +02:00
committed by George Pickett
parent eec5a6d6f1
commit c0cd5a7265
2 changed files with 84 additions and 2 deletions

View File

@@ -32,11 +32,28 @@ export type GuardedFetchResult = {
};
const DEFAULT_MAX_REDIRECTS = 3;
const CROSS_ORIGIN_REDIRECT_SENSITIVE_HEADERS = [
"authorization",
"proxy-authorization",
"cookie",
"cookie2",
];
function isRedirectStatus(status: number): boolean {
return status === 301 || status === 302 || status === 303 || status === 307 || status === 308;
}
function stripSensitiveHeadersForCrossOriginRedirect(init?: RequestInit): RequestInit | undefined {
if (!init?.headers) {
return init;
}
const headers = new Headers(init.headers);
for (const header of CROSS_ORIGIN_REDIRECT_SENSITIVE_HEADERS) {
headers.delete(header);
}
return { ...init, headers };
}
function buildAbortSignal(params: { timeoutMs?: number; signal?: AbortSignal }): {
signal?: AbortSignal;
cleanup: () => void;
@@ -99,6 +116,7 @@ export async function fetchWithSsrFGuard(params: GuardedFetchOptions): Promise<G
const visited = new Set<string>();
let currentUrl = params.url;
let currentInit = params.init ? { ...params.init } : undefined;
let redirectCount = 0;
while (true) {
@@ -125,7 +143,7 @@ export async function fetchWithSsrFGuard(params: GuardedFetchOptions): Promise<G
}
const init: RequestInit & { dispatcher?: Dispatcher } = {
...(params.init ? { ...params.init } : {}),
...(currentInit ? { ...currentInit } : {}),
redirect: "manual",
...(dispatcher ? { dispatcher } : {}),
...(signal ? { signal } : {}),
@@ -144,11 +162,15 @@ export async function fetchWithSsrFGuard(params: GuardedFetchOptions): Promise<G
await release(dispatcher);
throw new Error(`Too many redirects (limit: ${maxRedirects})`);
}
const nextUrl = new URL(location, parsedUrl).toString();
const nextParsedUrl = new URL(location, parsedUrl);
const nextUrl = nextParsedUrl.toString();
if (visited.has(nextUrl)) {
await release(dispatcher);
throw new Error("Redirect loop detected");
}
if (nextParsedUrl.origin !== parsedUrl.origin) {
currentInit = stripSensitiveHeadersForCrossOriginRedirect(currentInit);
}
visited.add(nextUrl);
void response.body?.cancel();
await closeDispatcher(dispatcher);