Skip to content

BaseHttpClient forwards Authorization across a cross-origin redirect #4134

Description

@janbuchar
  • 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 BaseHttpClient.sendRequest() throws on any redirect that preserves the request body #4133
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/http-client@4.0.0-beta.165, Node 26.8.2.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    t-toolingIssues with this label are in the ownership of the tooling team.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions