Skip to content

Commit 6d97790

Browse files
evanlucasrvagg
authored andcommitted
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: nodejs-private/node-private#47 Reviewed-By: Rod Vagg <rod@vagg.org> Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com> Reviewed-By: Douglas Wilson <doug@somethingdoug.com>
1 parent ad470e4 commit 6d97790

File tree

2 files changed

+49
-0
lines changed

2 files changed

+49
-0
lines changed

lib/_http_server.js

+3
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,9 @@ ServerResponse.prototype.writeHead = function(statusCode, reason, obj) {
206206
if (statusCode < 100 || statusCode > 999)
207207
throw new RangeError('Invalid status code: ' + statusCode);
208208

209+
if (common._checkInvalidHeaderChar(this.statusMessage))
210+
throw new Error('Invalid character in statusMessage.');
211+
209212
var statusLine = 'HTTP/1.1 ' + statusCode.toString() + ' ' +
210213
this.statusMessage + CRLF;
211214

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
'use strict';
2+
3+
var common = require('../common');
4+
var assert = require('assert');
5+
var http = require('http');
6+
7+
function explicit(req, res) {
8+
assert.throws(function() {
9+
res.writeHead(200, 'OK\r\nContent-Type: text/html\r\n');
10+
}, /Invalid character in statusMessage/);
11+
12+
assert.throws(function() {
13+
res.writeHead(200, 'OK\u010D\u010AContent-Type: gotcha\r\n');
14+
}, /Invalid character in statusMessage/);
15+
16+
res.statusMessage = 'OK';
17+
res.end();
18+
}
19+
20+
function implicit(req, res) {
21+
assert.throws(function() {
22+
res.statusMessage = 'OK\r\nContent-Type: text/html\r\n';
23+
res.writeHead(200);
24+
}, /Invalid character in statusMessage/);
25+
res.statusMessage = 'OK';
26+
res.end();
27+
}
28+
29+
var server = http.createServer(function(req, res) {
30+
if (req.url === '/explicit') {
31+
explicit(req, res);
32+
} else {
33+
implicit(req, res);
34+
}
35+
}).listen(common.PORT, common.mustCall(function() {
36+
var url = 'http://localhost:' + common.PORT;
37+
var left = 2;
38+
var check = common.mustCall(function(res) {
39+
left--;
40+
assert.notEqual(res.headers['content-type'], 'text/html');
41+
assert.notEqual(res.headers['content-type'], 'gotcha');
42+
if (left === 0) server.close();
43+
}, 2);
44+
http.get(url + '/explicit', check).end();
45+
http.get(url + '/implicit', check).end();
46+
}));

0 commit comments

Comments
 (0)