From 3614a173d0a0827bb9f7a1aa65bf9ccc9c7d6784 Mon Sep 17 00:00:00 2001 From: Evan Lucas Date: Mon, 13 Jun 2016 21:09:03 -0500 Subject: [PATCH] http: check reason chars in writeHead Previously, the reason argument passed to ServerResponse#writeHead was not being properly validated. One could pass CRLFs which could lead to http response splitting. This commit changes the behavior to throw an error in the event any invalid characters are included in the reason. CVE-2016-5325 PR-URL: https://github.com/nodejs/node-private/pull/48 Reviewed-By: Fedor Indutny Reviewed-By: Rod Vagg --- lib/http.js | 3 +++ .../test-http-status-reason-invalid-chars.js | 27 +++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 test/simple/test-http-status-reason-invalid-chars.js diff --git a/lib/http.js b/lib/http.js index 2814f6b43a5eab..b614384418f9be 100644 --- a/lib/http.js +++ b/lib/http.js @@ -1233,6 +1233,9 @@ ServerResponse.prototype.writeHead = function(statusCode) { if (statusCode < 100 || statusCode > 999) throw new RangeError('Invalid status code: ' + statusCode); + if (_checkInvalidHeaderChar(reasonPhrase)) + throw new Error('Invalid character in statusMessage.'); + var statusLine = 'HTTP/1.1 ' + statusCode.toString() + ' ' + reasonPhrase + CRLF; diff --git a/test/simple/test-http-status-reason-invalid-chars.js b/test/simple/test-http-status-reason-invalid-chars.js new file mode 100644 index 00000000000000..a2124b72427a7b --- /dev/null +++ b/test/simple/test-http-status-reason-invalid-chars.js @@ -0,0 +1,27 @@ +'use strict'; + +var common = require('../common'); +var assert = require('assert'); +var http = require('http'); + +var server = http.createServer(function(req, res) { + assert.throws(function() { + res.writeHead(200, 'OK\r\nContent-Type: text/html\r\n'); + }, /Invalid character in statusMessage/); + + assert.throws(function() { + res.writeHead(200, 'OK\u010D\u010AContent-Type: gotcha\r\n'); + }, /Invalid character in statusMessage/); + res.end(); +}).listen(common.PORT, common.mustCall(function() { + var url = 'http://localhost:' + common.PORT; + var left = 1; + var check = common.mustCall(function(res) { + res.resume(); + left--; + assert.notEqual(res.headers['content-type'], 'text/html'); + assert.notEqual(res.headers['content-type'], 'gotcha'); + if (left === 0) server.close(); + }, 1); + http.get(url + '/explicit', check); +}));