From e0d720c7f7f5a5de30ff049e0066e35e97cb86a7 Mon Sep 17 00:00:00 2001 From: Damien Arrachequesne Date: Sat, 2 Sep 2017 14:16:14 +0200 Subject: [PATCH] [fix] Check whether 'Origin' header has invalid characters (#531) Since the 'Origin' header is used as response header, a value with invalid characters would trigger 'The header content contains invalid characters' errors. Closes #517 --- lib/server.js | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/lib/server.js b/lib/server.js index f41d59eab..d52120a58 100644 --- a/lib/server.js +++ b/lib/server.js @@ -150,6 +150,13 @@ Server.prototype.verify = function (req, upgrade, fn) { return fn(Server.errors.UNKNOWN_TRANSPORT, false); } + // 'Origin' header check + var isOriginInvalid = checkInvalidHeaderChar(req.headers.origin); + if (isOriginInvalid) { + req.headers.origin = null; + return fn(Server.errors.BAD_REQUEST, false); + } + // sid check var sid = req._query.sid; if (sid) { @@ -512,3 +519,61 @@ function abortConnection (socket, code) { } socket.destroy(); } + +/* eslint-disable */ + +/** + * From https://github.com/nodejs/node/blob/v8.4.0/lib/_http_common.js#L303-L354 + * + * True if val contains an invalid field-vchar + * field-value = *( field-content / obs-fold ) + * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ] + * field-vchar = VCHAR / obs-text + * + * checkInvalidHeaderChar() is currently designed to be inlinable by v8, + * so take care when making changes to the implementation so that the source + * code size does not exceed v8's default max_inlined_source_size setting. + **/ +var validHdrChars = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, // 0 - 15 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16 - 31 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 32 - 47 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 48 - 63 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64 - 79 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 80 - 95 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96 - 111 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 112 - 127 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 128 ... + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // ... 255 +]; + +function checkInvalidHeaderChar(val) { + val += ''; + if (val.length < 1) + return false; + if (!validHdrChars[val.charCodeAt(0)]) + return true; + if (val.length < 2) + return false; + if (!validHdrChars[val.charCodeAt(1)]) + return true; + if (val.length < 3) + return false; + if (!validHdrChars[val.charCodeAt(2)]) + return true; + if (val.length < 4) + return false; + if (!validHdrChars[val.charCodeAt(3)]) + return true; + for (var i = 4; i < val.length; ++i) { + if (!validHdrChars[val.charCodeAt(i)]) + return true; + } + return false; +}