Vulnerability: Exposure of Sensitive Information in simple-get In versions of simple-get prior to 4.0.1, 3.1.1, and 2.8.2, when fetching a remote url with a cookie location response, headers will be followed, potentially resulting in an exposure of the session cookie to a third party.
Vulnerability ID: GHSA-wpg7-2c88-r8xv
CWE: CWE-200
Severity score: 7.5
Project: https://github.com/feross/simple-get
Published: 2022-01-28
File: index.js
Commit message: Merge pull request #73 from ranjit-git/master
Commit author: Feross Aboukhadijeh

Vulnerable version (before fix):
 function simpleGet (opts, cb) {   if (opts.json) opts.headers.accept = 'application/json'   if (opts.method) opts.method = opts.method.toUpperCase()    const protocol = opts.protocol === 'https:' ? https : http // Support http/https urls   const req = protocol.request(opts, res => {     if (opts.followRedirects !== false && res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {       opts.url = res.headers.location // Follow 3xx redirects       delete opts.headers.host // Discard `host` header on redirect (see #32)       res.resume() // Discard response        if (opts.method === 'POST' && [301, 302].includes(res.statusCode)) {         opts.method = 'GET' // On 301/302 redirect, change POST to GET (see #35)         delete opts.headers['content-length']; delete opts.headers['content-type']

Fixed version (after fix):
 function simpleGet (opts, cb) {   if (opts.json) opts.headers.accept = 'application/json'   if (opts.method) opts.method = opts.method.toUpperCase()    const originalHost = opts.hostname // hostname before potential redirect   const protocol = opts.protocol === 'https:' ? https : http // Support http/https urls   const req = protocol.request(opts, res => {     if (opts.followRedirects !== false && res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {       opts.url = res.headers.location // Follow 3xx redirects       delete opts.headers.host // Discard `host` header on redirect (see #32)       res.resume() // Discard response        const redirectHost = url.parse(opts.url).hostname // eslint-disable-line node/no-deprecated-api       // If redirected host is different than original host, drop headers to prevent cookie leak (#73)       if (redirectHost !== null && redirectHost !== originalHost) {         delete opts.headers.cookie         delete opts.headers.authorization       }        if (opts.method === 'POST' && [301, 302].includes(res.statusCode)) {         opts.method = 'GET' // On 301/302 redirect, change POST to GET (see #35)         delete opts.headers['content-length']; delete opts.headers['content-type']

Patch:
patch: @@ -44,13 +44,21 @@ function simpleGet (opts, cb) {
   if (opts.json) opts.headers.accept = 'application/json'
   if (opts.method) opts.method = opts.method.toUpperCase()
 
+  const originalHost = opts.hostname // hostname before potential redirect
   const protocol = opts.protocol === 'https:' ? https : http // Support http/https urls
   const req = protocol.request(opts, res => {
     if (opts.followRedirects !== false && res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
       opts.url = res.headers.location // Follow 3xx redirects
       delete opts.headers.host // Discard `host` header on redirect (see #32)
       res.resume() // Discard response
 
+      const redirectHost = url.parse(opts.url).hostname // eslint-disable-line node/no-deprecated-api
+      // If redirected host is different than original host, drop headers to prevent cookie leak (#73)
+      if (redirectHost !== null && redirectHost !== originalHost) {
+        delete opts.headers.cookie
+        delete opts.headers.authorization
+      }
+
       if (opts.method === 'POST' && [301, 302].includes(res.statusCode)) {
         opts.method = 'GET' // On 301/302 redirect, change POST to GET (see #35)
         delete opts.headers['content-length']; delete opts.headers['content-type']
path: index.js