From ef5cc13996b9765f306625ac5a0040bd445580eb Mon Sep 17 00:00:00 2001 From: Szymon Marczak <36894700+szmarczak@users.noreply.github.com> Date: Wed, 25 May 2022 19:38:49 +0200 Subject: [PATCH 1/5] Disable redirects to UNIX sockets --- source/core/index.ts | 5 +++++ test/redirects.ts | 31 ++++++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/source/core/index.ts b/source/core/index.ts index 63e2c5e7b..98820b403 100644 --- a/source/core/index.ts +++ b/source/core/index.ts @@ -727,6 +727,11 @@ export default class Request extends Duplex implements RequestEvents { const redirectBuffer = Buffer.from(response.headers.location, 'binary').toString(); const redirectUrl = new URL(redirectBuffer, url); + if (redirectUrl.protocol === 'unix:' || redirectUrl.hostname === 'unix') { + 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) { diff --git a/test/redirects.ts b/test/redirects.ts index 37d679270..1b6d4324b 100644 --- a/test/redirects.ts +++ b/test/redirects.ts @@ -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) => { @@ -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); From 60d1a5113de16abb6b66db19c5b02a34f96a68ef Mon Sep 17 00:00:00 2001 From: Szymon Marczak <36894700+szmarczak@users.noreply.github.com> Date: Wed, 25 May 2022 19:44:54 +0200 Subject: [PATCH 2/5] Enable UNIX to UNIX redirects --- source/core/index.ts | 2 +- test/unix-socket.ts | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/source/core/index.ts b/source/core/index.ts index 98820b403..9aceffed5 100644 --- a/source/core/index.ts +++ b/source/core/index.ts @@ -727,7 +727,7 @@ export default class Request extends Duplex implements RequestEvents { const redirectBuffer = Buffer.from(response.headers.location, 'binary').toString(); const redirectUrl = new URL(redirectBuffer, url); - if (redirectUrl.protocol === 'unix:' || redirectUrl.hostname === 'unix') { + if ((url as URL).hostname !== 'unix' && (redirectUrl.protocol === 'unix:' || redirectUrl.hostname === 'unix')) { this._beforeError(new RequestError('Cannot redirect to UNIX socket', {}, this)); return; } diff --git a/test/unix-socket.ts b/test/unix-socket.ts index f175e6ac5..059785ea7 100644 --- a/test/unix-socket.ts +++ b/test/unix-socket.ts @@ -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); @@ -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'); + }); } From 753b3b0d3c3a28459e4f21aa54f9ea00ff68ce15 Mon Sep 17 00:00:00 2001 From: Szymon Marczak <36894700+szmarczak@users.noreply.github.com> Date: Wed, 25 May 2022 20:00:58 +0200 Subject: [PATCH 3/5] readability --- source/core/index.ts | 3 ++- source/core/utils/is-unix-url.ts | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 source/core/utils/is-unix-url.ts diff --git a/source/core/index.ts b/source/core/index.ts index 9aceffed5..a941d05ab 100644 --- a/source/core/index.ts +++ b/source/core/index.ts @@ -34,6 +34,7 @@ import { } from './errors.js'; import type {PlainResponse} from './response.js'; import type {PromiseCookieJar, NativeRequestOptions, RetryOptions} from './options.js'; +import isUnixSocketURL from './utils/is-unix-url.js'; type Error = NodeJS.ErrnoException; @@ -727,7 +728,7 @@ export default class Request extends Duplex implements RequestEvents { const redirectBuffer = Buffer.from(response.headers.location, 'binary').toString(); const redirectUrl = new URL(redirectBuffer, url); - if ((url as URL).hostname !== 'unix' && (redirectUrl.protocol === 'unix:' || redirectUrl.hostname === 'unix')) { + if (!isUnixSocketURL(url as URL) && isUnixSocketURL(redirectUrl)) { this._beforeError(new RequestError('Cannot redirect to UNIX socket', {}, this)); return; } diff --git a/source/core/utils/is-unix-url.ts b/source/core/utils/is-unix-url.ts new file mode 100644 index 000000000..f36e662cb --- /dev/null +++ b/source/core/utils/is-unix-url.ts @@ -0,0 +1,5 @@ +import {URL} from 'url'; + +export default function isUnixSocketURL(url: URL) { + return url.protocol === 'unix:' || url.hostname === 'unix'; +} From 55a399eb1f5a315a3f5f7fda768d1c52ea7a5a7b Mon Sep 17 00:00:00 2001 From: Szymon Marczak <36894700+szmarczak@users.noreply.github.com> Date: Wed, 25 May 2022 20:03:43 +0200 Subject: [PATCH 4/5] xo --- source/core/index.ts | 2 +- source/core/utils/is-unix-url.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/source/core/index.ts b/source/core/index.ts index a941d05ab..63257356e 100644 --- a/source/core/index.ts +++ b/source/core/index.ts @@ -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-url.js'; import { RequestError, ReadError, @@ -34,7 +35,6 @@ import { } from './errors.js'; import type {PlainResponse} from './response.js'; import type {PromiseCookieJar, NativeRequestOptions, RetryOptions} from './options.js'; -import isUnixSocketURL from './utils/is-unix-url.js'; type Error = NodeJS.ErrnoException; diff --git a/source/core/utils/is-unix-url.ts b/source/core/utils/is-unix-url.ts index f36e662cb..af1dc3d09 100644 --- a/source/core/utils/is-unix-url.ts +++ b/source/core/utils/is-unix-url.ts @@ -1,5 +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'; } From d54cd3f85a2763f73084327a6e7690caa6472c5f Mon Sep 17 00:00:00 2001 From: Szymon Marczak <36894700+szmarczak@users.noreply.github.com> Date: Wed, 25 May 2022 20:05:56 +0200 Subject: [PATCH 5/5] rename --- source/core/index.ts | 2 +- source/core/utils/{is-unix-url.ts => is-unix-socket-url.ts} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename source/core/utils/{is-unix-url.ts => is-unix-socket-url.ts} (100%) diff --git a/source/core/index.ts b/source/core/index.ts index 63257356e..e521a1a56 100644 --- a/source/core/index.ts +++ b/source/core/index.ts @@ -23,7 +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-url.js'; +import isUnixSocketURL from './utils/is-unix-socket-url.js'; import { RequestError, ReadError, diff --git a/source/core/utils/is-unix-url.ts b/source/core/utils/is-unix-socket-url.ts similarity index 100% rename from source/core/utils/is-unix-url.ts rename to source/core/utils/is-unix-socket-url.ts