Showing with 40 additions and 6 deletions.
  1. +7 −3 index.js
  2. +2 −2 package-lock.json
  3. +1 −1 package.json
  4. +30 −0 test/test.js
10 changes: 7 additions & 3 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -392,8 +392,9 @@ RedirectableRequest.prototype._processResponse = function (response) {
var redirectUrlParts = url.parse(redirectUrl);
Object.assign(this._options, redirectUrlParts);

// Drop the confidential headers when redirecting to another domain
if (!(redirectUrlParts.host === currentHost || isSubdomainOf(redirectUrlParts.host, currentHost))) {
// Drop confidential headers when redirecting to another scheme:domain
if (redirectUrlParts.protocol !== currentUrlParts.protocol ||
!isSameOrSubdomain(redirectUrlParts.host, currentHost)) {
removeMatchingHeaders(/^(?:authorization|cookie)$/i, this._options.headers);
}

Expand Down Expand Up @@ -559,7 +560,10 @@ function abortRequest(request) {
request.abort();
}

function isSubdomainOf(subdomain, domain) {
function isSameOrSubdomain(subdomain, domain) {
if (subdomain === domain) {
return true;
}
const dot = subdomain.length - domain.length - 1;
return dot > 0 && subdomain[dot] === "." && subdomain.endsWith(domain);
}
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "follow-redirects",
"version": "1.14.7",
"version": "1.14.8",
"description": "HTTP and HTTPS modules that follow redirects.",
"license": "MIT",
"main": "index.js",
Expand Down
30 changes: 30 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1522,6 +1522,36 @@ describe("follow-redirects", function () {
});
});
});

it("drops the header when redirected to a different scheme", function () {
app.get("/a", redirectsTo(302, "http://localhost:3601/b"));
app.get("/b", function (req, res) {
res.end(JSON.stringify(req.headers));
});

var opts = url.parse("https://localhost:3601/a");
opts.ca = ca;
opts.headers = {};
opts.headers[header] = "the header value";

// Intercept the scheme
opts.beforeRedirect = function (options) {
assert.equal(options.protocol, "http:");
options.protocol = "https:";
};

return server.start(httpsOptions(app))
.then(asPromise(function (resolve, reject) {
https.get(opts, resolve).on("error", reject);
}))
.then(asPromise(function (resolve, reject, res) {
res.pipe(concat({ encoding: "string" }, resolve)).on("error", reject);
}))
.then(function (str) {
var body = JSON.parse(str);
assert.equal(body[header.toLowerCase()], undefined);
});
});
});

describe("when the followRedirects option is set to false", function () {
Expand Down