Skip to content

Commit 36d8cf5

Browse files
authoredOct 7, 2019
Use an EventEmitter to replay failed proxy connect HTTP requests (#77)
* Use an `EventEmitter` to replay failed proxy connect HTTP requests This is a fix for https://hackerone.com/reports/541502. Aborts the upstream proxy connection and instead uses a vanilla `EventEmitter` instance to replay the "data" events on to. This way, the node core `http` Client doesn't attempt to write the HTTP request that is intended to go to the destination server to the proxy server. Closes #76. * Adjust comment
1 parent 5252bb9 commit 36d8cf5

File tree

1 file changed

+15
-3
lines changed

1 file changed

+15
-3
lines changed
 

‎index.js

+15-3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
var net = require('net');
66
var tls = require('tls');
77
var url = require('url');
8+
var events = require('events');
89
var Agent = require('agent-base');
910
var inherits = require('util').inherits;
1011
var debug = require('debug')('https-proxy-agent');
@@ -154,20 +155,32 @@ HttpsProxyAgent.prototype.callback = function connect(req, opts, fn) {
154155
fn(null, sock);
155156
} else {
156157
// some other status code that's not 200... need to re-play the HTTP header
157-
// "data" events onto the socket once the HTTP machinery is attached so that
158-
// the user can parse and handle the error status code
158+
// "data" events onto the socket once the HTTP machinery is attached so
159+
// that the node core `http` can parse and handle the error status code
159160
cleanup();
160161

162+
// the original socket is closed, and a "fake socket" EventEmitter is
163+
// returned instead, so that the proxy doesn't get the HTTP request
164+
// written to it (which may contain `Authorization` headers or other
165+
// sensitive data).
166+
//
167+
// See: https://hackerone.com/reports/541502
168+
socket.destroy();
169+
socket = new events.EventEmitter();
170+
161171
// save a reference to the concat'd Buffer for the `onsocket` callback
162172
buffers = buffered;
163173

164174
// need to wait for the "socket" event to re-play the "data" events
165175
req.once('socket', onsocket);
176+
166177
fn(null, socket);
167178
}
168179
}
169180

170181
function onsocket(socket) {
182+
debug('replaying proxy buffer for failed request');
183+
171184
// replay the "buffers" Buffer onto the `socket`, since at this point
172185
// the HTTP module machinery has been hooked up for the user
173186
if (socket.listenerCount('data') > 0) {
@@ -177,7 +190,6 @@ HttpsProxyAgent.prototype.callback = function connect(req, opts, fn) {
177190
throw new Error('should not happen...');
178191
}
179192

180-
socket.resume();
181193
// nullify the cached Buffer instance
182194
buffers = null;
183195
}

2 commit comments

Comments
 (2)

jaimeborjas commented on Apr 17, 2020

@jaimeborjas

Security fixes

donurukiran commented on Apr 17, 2020

@donurukiran

done with few security issues

Please sign in to comment.