Skip to content

Commit 811b63c

Browse files
bennofsrvagg
authored andcommittedNov 27, 2018
http: disallow two-byte characters in URL path
CVE-2018-12116 Backport of b961d9f to 6.x Original commit: This commit changes node's handling of two-byte characters in the path component of an http URL. Previously, node would just strip the higher byte when generating the request. So this code: ``` http.request({host: "example.com", port: "80", "/N"}) ``` would request `http://example.com/.` (`.` is the character for the byte `0x2e`). This is not useful and can in some cases lead to filter evasion. With this change, the code generates `ERR_UNESCAPED_CHARACTERS`, just like space and control characters already did. PR-URL: #16237 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Anatoli Papirovski <apapirovski@mac.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Timothy Gu <timothygu99@gmail.com> PR-URL: nodejs-private/node-private#146 Fixes: nodejs-private/security#207 Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Timothy Gu <timothygu99@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
1 parent 9c268d0 commit 811b63c

File tree

2 files changed

+21
-8
lines changed

2 files changed

+21
-8
lines changed
 

‎lib/_http_client.js

+9-8
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const OutgoingMessage = require('_http_outgoing').OutgoingMessage;
1414
const Agent = require('_http_agent');
1515
const Buffer = require('buffer').Buffer;
1616

17+
const INVALID_PATH_REGEX = /[^\u0021-\u00ff]/;
1718

1819
function ClientRequest(options, cb) {
1920
var self = this;
@@ -43,14 +44,14 @@ function ClientRequest(options, cb) {
4344
if (self.agent && self.agent.protocol)
4445
expectedProtocol = self.agent.protocol;
4546

46-
if (options.path && /[\u0000-\u0020]/.test(options.path)) {
47-
// The actual regex is more like /[^A-Za-z0-9\-._~!$&'()*+,;=/:@]/
48-
// with an additional rule for ignoring percentage-escaped characters
49-
// but that's a) hard to capture in a regular expression that performs
50-
// well, and b) possibly too restrictive for real-world usage.
51-
// Restrict the filter to control characters and spaces.
52-
throw new TypeError('Request path contains unescaped characters');
53-
} else if (protocol !== expectedProtocol) {
47+
var path;
48+
if (options.path) {
49+
path = String(options.path);
50+
if (INVALID_PATH_REGEX.test(path))
51+
throw new TypeError('Request path contains unescaped characters');
52+
}
53+
54+
if (protocol !== expectedProtocol) {
5455
throw new Error('Protocol "' + protocol + '" not supported. ' +
5556
'Expected "' + expectedProtocol + '"');
5657
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
'use strict';
2+
3+
require('../common');
4+
5+
const http = require('http');
6+
const assert = require('assert');
7+
8+
assert.throws(() => {
9+
http.request({
10+
path: '/thisisinvalid\uffe2'
11+
}).end();
12+
}, /Request path contains unescaped characters/);

0 commit comments

Comments
 (0)
Please sign in to comment.