Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lib/_http_incoming.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ ObjectDefineProperty(IncomingMessage.prototype, 'headers', {
__proto__: null,
get: function() {
if (!this[kHeaders]) {
this[kHeaders] = {};
this[kHeaders] = { __proto__: null };

const src = this.rawHeaders;
const dst = this[kHeaders];
Expand Down Expand Up @@ -152,7 +152,7 @@ ObjectDefineProperty(IncomingMessage.prototype, 'trailers', {
__proto__: null,
get: function() {
if (!this[kTrailers]) {
this[kTrailers] = {};
this[kTrailers] = { __proto__: null };

const src = this.rawTrailers;
const dst = this[kTrailers];
Expand Down
2 changes: 1 addition & 1 deletion lib/internal/http2/compat.js
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ class Http2ServerRequest extends Readable {
// initialization using Object.create(null) in HTTP/2 is intentional.
this[kHeaders] = headers;
this[kRawHeaders] = rawHeaders;
this[kTrailers] = {};
this[kTrailers] = { __proto__: null };
this[kRawTrailers] = [];
this[kStream] = stream;
this[kAborted] = false;
Expand Down
9 changes: 4 additions & 5 deletions test/parallel/test-http-blank-header.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,10 @@ const net = require('net');
const server = http.createServer(common.mustCall((req, res) => {
assert.strictEqual(req.method, 'GET');
assert.strictEqual(req.url, '/blah');
assert.deepStrictEqual(req.headers, {
host: 'example.org:443',
origin: 'http://example.org',
cookie: ''
});
assert.deepStrictEqual(req.headers, { __proto__: null,
host: 'example.org:443',
origin: 'http://example.org',
cookie: '' });
}));


Expand Down
11 changes: 5 additions & 6 deletions test/parallel/test-http-client-headers-array.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,11 @@ const http = require('http');

function execute(options) {
http.createServer(common.mustCall(function(req, res) {
const expectHeaders = {
'x-foo': 'boom',
'cookie': 'a=1; b=2; c=3',
'connection': 'keep-alive',
'host': 'example.com',
};
const expectHeaders = { '__proto__': null,
'x-foo': 'boom',
'cookie': 'a=1; b=2; c=3',
'connection': 'keep-alive',
'host': 'example.com' };

// no Host header when you set headers an array
if (!Array.isArray(options.headers)) {
Expand Down
31 changes: 16 additions & 15 deletions test/parallel/test-http-content-length.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,17 @@ const assert = require('assert');
const http = require('http');
const Countdown = require('../common/countdown');

const expectedHeadersMultipleWrites = {
'connection': 'keep-alive',
'transfer-encoding': 'chunked',
};
const expectedHeadersMultipleWrites = { '__proto__': null,
'connection': 'keep-alive',
'transfer-encoding': 'chunked' };

const expectedHeadersEndWithData = {
'connection': 'keep-alive',
'content-length': String('hello world'.length),
};
const expectedHeadersEndWithData = { '__proto__': null,
'connection': 'keep-alive',
'content-length': String('hello world'.length) };

const expectedHeadersEndNoData = {
'connection': 'keep-alive',
'content-length': '0',
};
const expectedHeadersEndNoData = { '__proto__': null,
'connection': 'keep-alive',
'content-length': '0' };


const countdown = new Countdown(3, () => server.close());
Expand Down Expand Up @@ -62,7 +59,9 @@ server.listen(0, common.mustCall(function() {
req.write('hello ');
req.end('world');
req.on('response', common.mustCall((res) => {
assert.deepStrictEqual(res.headers, { ...expectedHeadersMultipleWrites, 'keep-alive': 'timeout=1' });
assert.deepStrictEqual(res.headers, {
'__proto__': null, ...expectedHeadersMultipleWrites, 'keep-alive': 'timeout=1',
});
res.resume();
}));

Expand All @@ -74,7 +73,9 @@ server.listen(0, common.mustCall(function() {
req.removeHeader('Date');
req.end('hello world');
req.on('response', common.mustCall((res) => {
assert.deepStrictEqual(res.headers, { ...expectedHeadersEndWithData, 'keep-alive': 'timeout=1' });
assert.deepStrictEqual(res.headers, {
'__proto__': null, ...expectedHeadersEndWithData, 'keep-alive': 'timeout=1',
});
res.resume();
}));

Expand All @@ -86,7 +87,7 @@ server.listen(0, common.mustCall(function() {
req.removeHeader('Date');
req.end();
req.on('response', common.mustCall((res) => {
assert.deepStrictEqual(res.headers, { ...expectedHeadersEndNoData, 'keep-alive': 'timeout=1' });
assert.deepStrictEqual(res.headers, { '__proto__': null, ...expectedHeadersEndNoData, 'keep-alive': 'timeout=1' });
res.resume();
}));

Expand Down
32 changes: 15 additions & 17 deletions test/parallel/test-http-multiple-headers.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,12 @@ const server = createServer(
'Host', host,
'Transfer-Encoding', 'chunked',
]);
assert.deepStrictEqual(req.headers, {
'connection': 'close',
'x-req-a': 'eee, fff, ggg, hhh',
'x-req-b': 'iii; jjj; kkk; lll',
host,
'transfer-encoding': 'chunked'
});
assert.deepStrictEqual(req.headers, { '__proto__': null,
'connection': 'close',
'x-req-a': 'eee, fff, ggg, hhh',
'x-req-b': 'iii; jjj; kkk; lll',
host,
'transfer-encoding': 'chunked' });
assert.deepStrictEqual(req.headersDistinct, Object.assign({ __proto__: null }, {
'connection': ['close'],
'x-req-a': ['eee', 'fff', 'ggg', 'hhh'],
Expand All @@ -41,7 +40,7 @@ const server = createServer(
'X-req-Y', 'zzz; www',
]);
assert.deepStrictEqual(
req.trailers, { 'x-req-x': 'xxx, yyy', 'x-req-y': 'zzz; www' }
req.trailers, { '__proto__': null, 'x-req-x': 'xxx, yyy', 'x-req-y': 'zzz; www' }
);
assert.deepStrictEqual(
req.trailersDistinct,
Expand Down Expand Up @@ -124,14 +123,13 @@ server.listen(0, common.mustCall(() => {
'x-res-d', 'JJJ; KKK; LLL',
'Transfer-Encoding', 'chunked',
]);
assert.deepStrictEqual(res.headers, {
'x-res-a': 'AAA, BBB, CCC',
'x-res-b': 'DDD; EEE; FFF; GGG',
'connection': 'close',
'x-res-c': 'HHH, III',
'x-res-d': 'JJJ; KKK; LLL',
'transfer-encoding': 'chunked'
});
assert.deepStrictEqual(res.headers, { '__proto__': null,
'x-res-a': 'AAA, BBB, CCC',
'x-res-b': 'DDD; EEE; FFF; GGG',
'connection': 'close',
'x-res-c': 'HHH, III',
'x-res-d': 'JJJ; KKK; LLL',
'transfer-encoding': 'chunked' });
assert.deepStrictEqual(res.headersDistinct, Object.assign({ __proto__: null }, {
'x-res-a': [ 'AAA', 'BBB', 'CCC' ],
'x-res-b': [ 'DDD; EEE; FFF; GGG' ],
Expand All @@ -149,7 +147,7 @@ server.listen(0, common.mustCall(() => {
]);
assert.deepStrictEqual(
res.trailers,
{ 'x-res-x': 'XXX, YYY', 'x-res-y': 'ZZZ; WWW' }
{ '__proto__': null, 'x-res-x': 'XXX, YYY', 'x-res-y': 'ZZZ; WWW' }
);
assert.deepStrictEqual(
res.trailersDistinct,
Expand Down
28 changes: 13 additions & 15 deletions test/parallel/test-http-raw-headers.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,11 @@ http.createServer(common.mustCall(function(req, res) {
'Connection',
'keep-alive',
];
const expectHeaders = {
'host': `localhost:${this.address().port}`,
'transfer-encoding': 'CHUNKED',
'x-bar': 'yoyoyo',
'connection': 'keep-alive'
};
const expectHeaders = { '__proto__': null,
'host': `localhost:${this.address().port}`,
'transfer-encoding': 'CHUNKED',
'x-bar': 'yoyoyo',
'connection': 'keep-alive' };
const expectRawTrailers = [
'x-bAr',
'yOyOyOy',
Expand All @@ -52,7 +51,7 @@ http.createServer(common.mustCall(function(req, res) {
'X-baR',
'OyOyOyO',
];
const expectTrailers = { 'x-bar': 'yOyOyOy, OyOyOyO, yOyOyOy, OyOyOyO' };
const expectTrailers = { '__proto__': null, 'x-bar': 'yOyOyOy, OyOyOyO, yOyOyOy, OyOyOyO' };

this.close();

Expand Down Expand Up @@ -98,13 +97,12 @@ http.createServer(common.mustCall(function(req, res) {
'Transfer-Encoding',
'chunked',
];
const expectHeaders = {
'keep-alive': 'timeout=1',
'trailer': 'x-foo',
'date': null,
'connection': 'keep-alive',
'transfer-encoding': 'chunked'
};
const expectHeaders = { '__proto__': null,
'keep-alive': 'timeout=1',
'trailer': 'x-foo',
'date': null,
'connection': 'keep-alive',
'transfer-encoding': 'chunked' };
res.rawHeaders[5] = null;
res.headers.date = null;
assert.deepStrictEqual(res.rawHeaders, expectRawHeaders);
Expand All @@ -120,7 +118,7 @@ http.createServer(common.mustCall(function(req, res) {
'X-foO',
'OxOxOxO',
];
const expectTrailers = { 'x-foo': 'xOxOxOx, OxOxOxO, xOxOxOx, OxOxOxO' };
const expectTrailers = { '__proto__': null, 'x-foo': 'xOxOxOx, OxOxOxO, xOxOxOx, OxOxOxO' };

assert.deepStrictEqual(res.rawTrailers, expectRawTrailers);
assert.deepStrictEqual(res.trailers, expectTrailers);
Expand Down
2 changes: 1 addition & 1 deletion test/parallel/test-http-remove-header-stays-removed.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ const server = http.createServer(common.mustCall(function(request, response) {
server.listen(0, common.mustCall(function() {
http.get({ port: this.address().port }, common.mustCall((res) => {
assert.strictEqual(res.statusCode, 200);
assert.deepStrictEqual(res.headers, { date: 'coffee o clock' });
assert.deepStrictEqual(res.headers, { __proto__: null, date: 'coffee o clock' });

let response = '';
res.setEncoding('ascii');
Expand Down
97 changes: 97 additions & 0 deletions test/parallel/test-http-server-headers-null-proto.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
'use strict';

const common = require('../common');
const assert = require('assert');
const http = require('http');
const net = require('net');

// Test 1: req.headers has a null prototype
{
const server = http.createServer(common.mustCall((req, res) => {
assert.strictEqual(Object.getPrototypeOf(req.headers), null);
res.end();
}));

server.listen(0, common.mustCall(() => {
const port = server.address().port;

const client = net.connect(port, common.mustCall(() => {
client.write(
'GET / HTTP/1.1\r\n' +
'Host: localhost\r\n' +
'Connection: close\r\n' +
'\r\n',
);
}));

client.on('end', common.mustCall(() => {
server.close();
}));

client.resume();
}));
}

// Test 2: req.trailers has a null prototype
Comment thread
mcollina marked this conversation as resolved.
{
const server = http.createServer(common.mustCall((req, res) => {
res.setHeader('Transfer-Encoding', 'chunked');
res.write('Hello');
res.addTrailers({
'X-Trailer': 'test',
});
res.end();
}));

server.listen(0, common.mustCall(() => {
const port = server.address().port;

const client = net.connect(port, common.mustCall(() => {
client.write(
'GET / HTTP/1.1\r\n' +
'Host: localhost\r\n' +
'TE: trailers\r\n' +
'Connection: close\r\n' +
'\r\n',
);
}));

client.on('data', () => {});

client.on('end', common.mustCall(() => {
server.close();
}));
}));
}

// Test 3: req.headers with __proto__ header (should not pollute prototype)
{
const server = http.createServer(common.mustCall((req, res) => {
assert.strictEqual(Object.getPrototypeOf(req.headers), null);
// The __proto__ header should be stored as a regular property
assert.strictEqual(
Object.getOwnPropertyDescriptor(req.headers, '__proto__').value, 'test',
);
res.end();
}));

server.listen(0, common.mustCall(() => {
const port = server.address().port;

const client = net.connect(port, common.mustCall(() => {
client.write(
'GET / HTTP/1.1\r\n' +
'Host: localhost\r\n' +
'__proto__: test\r\n' +
'Connection: close\r\n' +
'\r\n',
);
}));

client.on('end', common.mustCall(() => {
server.close();
}));

client.resume();
}));
}
2 changes: 1 addition & 1 deletion test/parallel/test-http-upgrade-agent.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ server.listen(0, '127.0.0.1', common.mustCall(function() {
assert.strictEqual(recvData.toString(), 'nurtzo');
}));

const expectedHeaders = { 'hello': 'world',
const expectedHeaders = { '__proto__': null, 'hello': 'world',
'connection': 'upgrade',
'upgrade': 'websocket' };
assert.deepStrictEqual(expectedHeaders, res.headers);
Expand Down
3 changes: 2 additions & 1 deletion test/parallel/test-http-upgrade-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ server.listen(0, common.mustCall(function() {
const expectedHeaders = {
hello: 'world',
connection: 'upgrade',
upgrade: 'websocket'
upgrade: 'websocket',
__proto__: null
};
assert.deepStrictEqual(res.headers, expectedHeaders);
socket.end();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ server.on('upgrade', common.mustCall(function(req, socket, upgradeHead) {
req.on('end', common.mustCall(() => {
assert.strictEqual(reqBodyLength, EXPECTED_BODY_LENGTH);

assert.deepStrictEqual(req.trailers, { 'extra-data': 'abc' });
assert.deepStrictEqual(req.trailers, { '__proto__': null, 'extra-data': 'abc' });

// Defer upgrade stream read slightly to make sure it doesn't start
// streaming along with the request body, until we actually read it:
Expand Down
1 change: 1 addition & 0 deletions test/parallel/test-http2-compat-serverrequest-trailers.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ server.listen(0, common.mustCall(function() {
request.on('data', common.mustCallAtLeast((chunk) => data += chunk));
request.on('end', common.mustCall(() => {
const trailers = request.trailers;
assert.strictEqual(Object.getPrototypeOf(trailers), null);
for (const [name, value] of Object.entries(expectedTrailers)) {
assert.strictEqual(trailers[name], value);
}
Expand Down
Loading