#4134·crawlee

BaseHttpClient forwards Authorization across a cross-origin redirect

Author: janbucharCreated Sep 16, 2026Updated Sep 16, 2026
Labelst-tooling
  • buildRedirectRequest() copies every header of the previous request onto the next one, with no origin check
  • the Fetch standard drops Authorization when a redirect changes origin, and native fetch does; the manual redirect loop does not, so a token sent to one host is handed to whatever host it redirects to
  • relevant wherever sendRequest carries credentials and the redirect target isn't trusted
  • same method as #4133
javascript
import { createServer } from 'node:http';
import { FetchHttpClient } from '@crawlee/http-client';

const victim = createServer((req, res) => {
    console.log('second host saw:', req.headers.authorization ?? '(none)');
    res.writeHead(200).end('ok');
});
await new Promise((resolve) => victim.listen(0, resolve));

const redirector = createServer((_req, res) => {
    res.writeHead(302, { location: `http://127.0.0.1:${victim.address().port}/end` });
    res.end();
});
await new Promise((resolve) => redirector.listen(0, resolve));
const url = `http://127.0.0.1:${redirector.address().port}/start`;

await new FetchHttpClient().sendRequest(new Request(url, { headers: { authorization: 'Bearer secret' } }));
// second host saw: Bearer secret
await fetch(url, { headers: { authorization: 'Bearer secret' } });
// second host saw: (none)

@crawlee/[email protected], Node 26.8.2.