Skip to content

Commit 0e97dba

Browse files
fix: Do not crash when a ill formed URL request is proxied (#19274)
1 parent 570f91d commit 0e97dba

File tree

3 files changed

+57
-1
lines changed

3 files changed

+57
-1
lines changed

packages/https-proxy/lib/server.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,16 @@ class Server {
3434
}
3535

3636
connect (req, browserSocket, head, options = {}) {
37+
// the SNI server requires a hostname, so if the hostname is blank,
38+
// destroy the socket and fail fast
39+
const { hostname } = url.parse(`https://${req.url}`)
40+
41+
if (!hostname) {
42+
browserSocket.destroy()
43+
44+
return debug(`Invalid hostname for request url ${req.url}`)
45+
}
46+
3747
// don't buffer writes - thanks a lot, Nagle
3848
// https://github.com/cypress-io/cypress/issues/3192
3949
browserSocket.setNoDelay(true)
@@ -199,6 +209,17 @@ class Server {
199209

200210
return makeConnection(port)
201211
})
212+
.catch((err) => {
213+
debug('Error making connection %o', { err })
214+
215+
browserSocket.destroy(err)
216+
217+
leave()
218+
219+
if (this._onError) {
220+
return this._onError(err, browserSocket, head)
221+
}
222+
})
202223
})
203224
}
204225

packages/https-proxy/test/integration/proxy_spec.js

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,25 @@ describe('Proxy', () => {
215215
expect(this.proxy._generateMissingCertificates).to.be.calledTwice
216216
})
217217
})
218+
219+
// https://github.com/cypress-io/cypress/issues/9220
220+
it('handles errors with addContext', async function () {
221+
this.sandbox.spy(this.proxy, 'connect')
222+
this.sandbox.stub(this.proxy._sniServer, 'addContext').throws(new Error('error adding context'))
223+
224+
return request({
225+
strictSSL: false,
226+
url: 'https://localhost:8443/',
227+
proxy: 'http://localhost:3333',
228+
}).catch(() => {
229+
// This scenario will cause an error but we should clean
230+
// ensure the outgoing socket created for this connection was destroyed
231+
expect(this.proxy.connect).calledOnce
232+
const socket = this.proxy.connect.getCalls()[0].args[1]
233+
234+
expect(socket.destroyed).to.be.true
235+
})
236+
})
218237
})
219238

220239
context('closing', () => {
@@ -229,7 +248,7 @@ describe('Proxy', () => {
229248
}).then(() => {
230249
return proxy.start(3333)
231250
}).then(() => {
232-
// force this to reject if its called
251+
// force this to reject if its called
233252
this.sandbox.stub(this.proxy, '_generateMissingCertificates').rejects(new Error('should not call'))
234253

235254
return request({

packages/https-proxy/test/unit/server_spec.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,5 +92,21 @@ describe('lib/server', () => {
9292
srv._makeConnection(socket, head, '443', '%7Balgolia_application_id%7D-dsn.algolia.net')
9393
})
9494
})
95+
96+
// https://github.com/cypress-io/cypress/issues/9220
97+
it('does not crash when a blank URL is parsed and instead only destroys the socket', function (done) {
98+
const socket = new EE()
99+
100+
socket.destroy = this.sandbox.stub()
101+
const head = {}
102+
103+
this.setup()
104+
.then((srv) => {
105+
srv.connect({ url: '%20:443' }, socket, head)
106+
expect(socket.destroy).to.be.calledOnce
107+
108+
done()
109+
})
110+
})
95111
})
96112
})

0 commit comments

Comments
 (0)