Reject invalid redirects

Fixes #234.
This commit is contained in:
Rob Wu
2020-05-06 23:25:17 +02:00
parent 0a3b8e965f
commit a9e06a9dab
3 changed files with 23 additions and 2 deletions

View File

@@ -171,9 +171,12 @@ function onProxyResponse(proxy, proxyReq, proxyRes, req, res) {
// Handle redirects
if (statusCode === 301 || statusCode === 302 || statusCode === 303 || statusCode === 307 || statusCode === 308) {
var locationHeader = proxyRes.headers.location;
var parsedLocation;
if (locationHeader) {
locationHeader = url.resolve(requestState.location.href, locationHeader);
parsedLocation = parseURL(locationHeader);
}
if (parsedLocation) {
if (statusCode === 301 || statusCode === 302 || statusCode === 303) {
// Exclude 307 & 308, because they are rare, and require preserving the method + request body
requestState.redirectCount_ = requestState.redirectCount_ + 1 || 1;
@@ -186,7 +189,7 @@ function onProxyResponse(proxy, proxyReq, proxyRes, req, res) {
req.method = 'GET';
req.headers['content-length'] = '0';
delete req.headers['content-type'];
requestState.location = parseURL(locationHeader);
requestState.location = parsedLocation;
// Remove all listeners (=reset events to initial state)
req.removeAllListeners();

View File

@@ -114,6 +114,11 @@ nock('http://example.com')
.get('/redirectwithoutlocation')
.reply(302, 'maybe found')
.get('/redirectinvalidlocation')
.reply(302, 'redirecting to junk...', {
Location: 'http:///',
})
.get('/proxyerror')
.replyWithError('throw node')
;

View File

@@ -246,6 +246,19 @@ describe('Basic functionality', function() {
.expect(302, 'maybe found', done);
});
it('GET with 302 redirect to an invalid Location should not be followed', function(done) {
// There is nothing to follow, so let the browser decide what to do with it.
request(cors_anywhere)
.get('/example.com/redirectinvalidlocation')
.redirects(0)
.expect('Access-Control-Allow-Origin', '*')
.expect('x-request-url', 'http://example.com/redirectinvalidlocation')
.expect('x-final-url', 'http://example.com/redirectinvalidlocation')
.expect('access-control-expose-headers', /x-final-url/)
.expect('Location', 'http:///')
.expect(302, 'redirecting to junk...', done);
});
it('POST with 307 redirect should not be handled', function(done) {
// Because of implementation difficulties (having to keep the request body
// in memory), handling HTTP 307/308 redirects is deferred to the requestor.