diff --git a/lib/_http_client.js b/lib/_http_client.js index aef05eb8fa2299..644c0bb8c89e70 100644 --- a/lib/_http_client.js +++ b/lib/_http_client.js @@ -41,13 +41,16 @@ function ClientRequest(options, cb) { if (self.agent && self.agent.protocol) expectedProtocol = self.agent.protocol; - if (options.path && / /.test(options.path)) { + if (options.path && ! /^[\x00-\x08\x0E-\x1F\x21-\x7F]*$/.test(options.path)) { // The actual regex is more like /[^A-Za-z0-9\-._~!$&'()*+,;=/:@]/ // with an additional rule for ignoring percentage-escaped characters // but that's a) hard to capture in a regular expression that performs - // well, and b) possibly too restrictive for real-world usage. That's - // why it only scans for spaces because those are guaranteed to create - // an invalid request. + // well, and b) possibly too restrictive for real-world usage. + // + // This regex rejects paths with whitespace (U+0009, U+000A, U+000B, + // U+000C, U+000D and U+0020) as those can have special meaning in the HTTP + // protocol, as well as paths with non-ASCII characters, (to deprecate + // previous buggy behaviour). throw new TypeError('Request path contains unescaped characters.'); } else if (protocol !== expectedProtocol) { throw new Error('Protocol "' + protocol + '" not supported. ' + diff --git a/test/parallel/test-http-client-unescaped-path.js b/test/parallel/test-http-client-unescaped-path.js index 1536916ae9b49c..3fe5db402cf8f7 100644 --- a/test/parallel/test-http-client-unescaped-path.js +++ b/test/parallel/test-http-client-unescaped-path.js @@ -3,7 +3,18 @@ var common = require('../common'); var assert = require('assert'); var http = require('http'); -assert.throws(function() { - // Path with spaces in it should throw. - http.get({ path: 'bad path' }, assert.fail); -}, /contains unescaped characters/); +for (var path of ['bad path', 'line\nfeed', 'carriage\rreturn', 'tab\t']) { + assert.throws( + function() { http.get({ path: path }, assert.fail); }, + /contains unescaped characters/, + 'Path "' + path + '" with whitespace should throw' + ); +} + +for (var path of ['caf\u00e9', '\u0649\u0644\u0649', '💩' /* U+1F4A9 */ ]) { + assert.throws( + function() { http.get({ path: path }, assert.fail); }, + /contains unescaped characters/, + 'Path "' + path + '" with non-ASCII characters should throw' + ); +}