Skip to content

Commit 3c293ba

Browse files
piscisaureusisaacs
authored andcommitted
http: protect against response splitting attacks
1 parent 0e95ea4 commit 3c293ba

File tree

2 files changed

+69
-0
lines changed

2 files changed

+69
-0
lines changed

lib/http.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,11 @@ OutgoingMessage.prototype._storeHeader = function(firstLine, headers) {
551551
var self = this;
552552

553553
function store(field, value) {
554+
// Protect against response splitting. The if statement is there to
555+
// minimize the performance impact in the common case.
556+
if (/[\r\n]/.test(value))
557+
value = value.replace(/[\r\n]+[ \t]*/g, '');
558+
554559
messageHeader += field + ': ' + value + CRLF;
555560

556561
if (connectionExpression.test(field)) {
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// Copyright Joyent, Inc. and other Node contributors.
2+
//
3+
// Permission is hereby granted, free of charge, to any person obtaining a
4+
// copy of this software and associated documentation files (the
5+
// "Software"), to deal in the Software without restriction, including
6+
// without limitation the rights to use, copy, modify, merge, publish,
7+
// distribute, sublicense, and/or sell copies of the Software, and to permit
8+
// persons to whom the Software is furnished to do so, subject to the
9+
// following conditions:
10+
//
11+
// The above copyright notice and this permission notice shall be included
12+
// in all copies or substantial portions of the Software.
13+
//
14+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15+
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17+
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18+
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19+
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20+
// USE OR OTHER DEALINGS IN THE SOFTWARE.
21+
22+
var common = require('../common'),
23+
assert = require('assert'),
24+
http = require('http');
25+
26+
var testIndex = 0,
27+
responses = 0;
28+
29+
var server = http.createServer(function(req, res) {
30+
switch (testIndex++) {
31+
case 0:
32+
res.writeHead(200, { test: 'foo \r\ninvalid: bar' });
33+
break;
34+
case 1:
35+
res.writeHead(200, { test: 'foo \ninvalid: bar' });
36+
break;
37+
case 2:
38+
res.writeHead(200, { test: 'foo \rinvalid: bar' });
39+
break;
40+
case 3:
41+
res.writeHead(200, { test: 'foo \n\n\ninvalid: bar' });
42+
break;
43+
case 4:
44+
res.writeHead(200, { test: 'foo \r\n \r\n \r\ninvalid: bar' });
45+
server.close();
46+
break;
47+
default:
48+
assert(false);
49+
}
50+
res.end('Hi mars!');
51+
});
52+
server.listen(common.PORT);
53+
54+
for (var i = 0; i < 5; i++) {
55+
var req = http.get({ port: common.PORT, path: '/' }, function(res) {
56+
assert.strictEqual(res.headers.test, 'foo invalid: bar');
57+
assert.strictEqual(res.headers.invalid, undefined);
58+
responses++;
59+
});
60+
}
61+
62+
process.on('exit', function() {
63+
assert.strictEqual(responses, 5);
64+
});

0 commit comments

Comments
 (0)