Skip to content

Commit

Permalink
Disable redirects to UNIX sockets (#2047)
Browse files Browse the repository at this point in the history
  • Loading branch information
szmarczak committed May 25, 2022
1 parent 4cdcca3 commit 861ccd9
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 1 deletion.
6 changes: 6 additions & 0 deletions source/core/index.ts
Expand Up @@ -23,6 +23,7 @@ import calculateRetryDelay from './calculate-retry-delay.js';
import Options, {OptionsError, OptionsInit} from './options.js';
import {isResponseOk, Response} from './response.js';
import isClientRequest from './utils/is-client-request.js';
import isUnixSocketURL from './utils/is-unix-socket-url.js';
import {
RequestError,
ReadError,
Expand Down Expand Up @@ -727,6 +728,11 @@ export default class Request extends Duplex implements RequestEvents<Request> {
const redirectBuffer = Buffer.from(response.headers.location, 'binary').toString();
const redirectUrl = new URL(redirectBuffer, url);

if (!isUnixSocketURL(url as URL) && isUnixSocketURL(redirectUrl)) {
this._beforeError(new RequestError('Cannot redirect to UNIX socket', {}, this));
return;
}

// Redirecting to a different site, clear sensitive data.
if (redirectUrl.hostname !== (url as URL).hostname || redirectUrl.port !== (url as URL).port) {
if ('host' in updatedOptions.headers) {
Expand Down
6 changes: 6 additions & 0 deletions source/core/utils/is-unix-socket-url.ts
@@ -0,0 +1,6 @@
import {URL} from 'url';

// eslint-disable-next-line @typescript-eslint/naming-convention
export default function isUnixSocketURL(url: URL) {
return url.protocol === 'unix:' || url.hostname === 'unix';
}
31 changes: 30 additions & 1 deletion test/redirects.ts
Expand Up @@ -2,7 +2,7 @@ import {Buffer} from 'buffer';
import test from 'ava';
import {Handler} from 'express';
import nock from 'nock';
import got, {MaxRedirectsError} from '../source/index.js';
import got, {MaxRedirectsError, RequestError} from '../source/index.js';
import withServer, {withHttpsServer} from './helpers/with-server.js';

const reachedHandler: Handler = (_request, response) => {
Expand All @@ -28,6 +28,35 @@ const relativeHandler: Handler = (_request, response) => {
response.end();
};

const unixProtocol: Handler = (_request, response) => {
response.writeHead(302, {
location: 'unix:/var/run/docker.sock:/containers/json',
});
response.end();
};

const unixHostname: Handler = (_request, response) => {
response.writeHead(302, {
location: 'http://unix:/var/run/docker.sock:/containers/json',
});
response.end();
};

test('cannot redirect to unix protocol', withServer, async (t, server, got) => {
server.get('/protocol', unixProtocol);
server.get('/hostname', unixHostname);

await t.throwsAsync(got('protocol'), {
message: 'Cannot redirect to UNIX socket',
instanceOf: RequestError,
});

await t.throwsAsync(got('hostname'), {
message: 'Cannot redirect to UNIX socket',
instanceOf: RequestError,
});
});

test('follows redirect', withServer, async (t, server, got) => {
server.get('/', reachedHandler);
server.get('/finite', finiteHandler);
Expand Down
15 changes: 15 additions & 0 deletions test/unix-socket.ts
Expand Up @@ -9,6 +9,13 @@ const okHandler: Handler = (_request, response) => {
response.end('ok');
};

const redirectHandler: Handler = (_request, response) => {
response.writeHead(302, {
location: 'foo',
});
response.end();
};

if (process.platform !== 'win32') {
test('works', withSocketServer, async (t, server) => {
server.on('/', okHandler);
Expand Down Expand Up @@ -53,4 +60,12 @@ if (process.platform !== 'win32') {
const url = format('http://unix:%s:%s', server.socketPath, '/?a=1');
t.is((await got(url)).body, 'ok');
});

test('redirects work', withSocketServer, async (t, server) => {
server.on('/', redirectHandler);
server.on('/foo', okHandler);

const url = format('http://unix:%s:%s', server.socketPath, '/');
t.is((await got(url)).body, 'ok');
});
}

0 comments on commit 861ccd9

Please sign in to comment.