From efe55f77b61fdba6b53ce94dad32166549cff7fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Afonso=20Janu=C3=A1rio?= Date: Thu, 3 Sep 2026 10:23:44 +0100 Subject: [PATCH] fix: reject unencoded unix socket URLs instead of silently hitting localhost If the socket path in a http+unix:// or https+unix:// URL still has literal slashes instead of being percent-encoded, the URL parser can't tell the socket path apart from a regular path. It ends up with an empty hostname, and superagent was falling back to a plain HTTP request against localhost with a null path, which just fails with a confusing ECONNREFUSED that has nothing to do with the actual mistake. Now this case is caught right where the socket path gets parsed out, and the request fails with a message that tells you what to do about it. Fixes #1767 --- src/node/index.js | 12 ++++++++++++ test/node/unix-sockets.js | 19 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/src/node/index.js b/src/node/index.js index c21231ad7..b5f45458a 100644 --- a/src/node/index.js +++ b/src/node/index.js @@ -709,6 +709,16 @@ Request.prototype.request = function () { // get the protocol protocol = `${protocol.split('+')[0]}:`; + if (!url.hostname) { + // the socket path wasn't percent-encoded, so the URL parser folded it + // into the pathname and left us with nothing to connect to. Bail out + // here instead of silently falling back to a plain host request. + this._unixSocketError = new Error( + 'Invalid unix socket URL. A unix socket path must be percent-encoded (replace "/" with "%2F"), e.g. http+unix://%2Ftmp%2Fmy.sock/path' + ); + return; + } + // get the socket path options.socketPath = url.hostname.replace(/%2F/g, '/'); url.host = ''; @@ -985,6 +995,8 @@ Request.prototype._end = function () { new Error('The request has been aborted even before .end() was called') ); + if (this._unixSocketError) return this.callback(this._unixSocketError); + let data = this._data; const { req } = this; const { method } = this; diff --git a/test/node/unix-sockets.js b/test/node/unix-sockets.js index a443079af..8eb4bd155 100644 --- a/test/node/unix-sockets.js +++ b/test/node/unix-sockets.js @@ -72,6 +72,25 @@ describe('[unix-sockets] http', () => { }); }); +describe('[unix-sockets] invalid path', () => { + if (process.platform === 'win32') { + return; + } + + it('rejects with a clear error instead of hitting the wrong host', (done) => { + // the socket path here has literal slashes instead of being + // percent-encoded, so the URL parser can't tell it apart from a path + request + .get(`http+unix://${httpSockPath}/request/path`) + .end((error, res) => { + assert(error); + assert(/percent-encoded/.test(error.message)); + assert.strictEqual(res, undefined); + done(); + }); + }); +}); + describe('[unix-sockets] https', () => { if (process.platform === 'win32') { return;