Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit df31f71

Browse filesBrowse files
rexagodBridgeAR
authored andcommitted
http2: header field valid checks
checks validity for request, writeHead, and setHeader methods PR-URL: #33193 Refs: #29829 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Robert Nagy <ronagy@icloud.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
1 parent 2c0a4fa commit df31f71
Copy full SHA for df31f71

File tree

Expand file treeCollapse file tree

4 files changed

+84
-2
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

4 files changed

+84
-2
lines changed
Open diff view settings
Collapse file

‎lib/internal/http2/compat.js‎

Copy file name to clipboardExpand all lines: lib/internal/http2/compat.js
+12-1Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,13 @@ const {
4646
hideStackFrames
4747
} = require('internal/errors');
4848
const { validateString } = require('internal/validators');
49-
const { kSocket, kRequest, kProxySocket } = require('internal/http2/util');
49+
const {
50+
kSocket,
51+
kRequest,
52+
kProxySocket,
53+
assertValidPseudoHeader
54+
} = require('internal/http2/util');
55+
const { _checkIsHttpToken: checkIsHttpToken } = require('_http_common');
5056

5157
const kBeginSend = Symbol('begin-send');
5258
const kState = Symbol('state');
@@ -590,6 +596,11 @@ class Http2ServerResponse extends Stream {
590596
return;
591597
}
592598

599+
if (name[0] === ':')
600+
assertValidPseudoHeader(name);
601+
else if (!checkIsHttpToken(name))
602+
this.destroy(new ERR_INVALID_HTTP_TOKEN('Header name', name));
603+
593604
this[kHeaders][name] = value;
594605
}
595606

Collapse file

‎lib/internal/http2/core.js‎

Copy file name to clipboardExpand all lines: lib/internal/http2/core.js
+16-1Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const {
99
MathMin,
1010
ObjectAssign,
1111
ObjectCreate,
12+
ObjectKeys,
1213
ObjectDefineProperty,
1314
ObjectPrototypeHasOwnProperty,
1415
Promise,
@@ -35,7 +36,10 @@ const tls = require('tls');
3536
const { URL } = require('url');
3637
const { setImmediate } = require('timers');
3738

38-
const { kIncomingMessage } = require('_http_common');
39+
const {
40+
kIncomingMessage,
41+
_checkIsHttpToken: checkIsHttpToken
42+
} = require('_http_common');
3943
const { kServerResponse } = require('_http_server');
4044
const JSStreamSocket = require('internal/js_stream_socket');
4145

@@ -88,6 +92,7 @@ const {
8892
ERR_INVALID_ARG_TYPE,
8993
ERR_INVALID_CALLBACK,
9094
ERR_INVALID_CHAR,
95+
ERR_INVALID_HTTP_TOKEN,
9196
ERR_INVALID_OPT_VALUE,
9297
ERR_OUT_OF_RANGE,
9398
ERR_SOCKET_CLOSED
@@ -108,6 +113,7 @@ const { onServerStream,
108113

109114
const {
110115
assertIsObject,
116+
assertValidPseudoHeader,
111117
assertValidPseudoHeaderResponse,
112118
assertValidPseudoHeaderTrailer,
113119
assertWithinRange,
@@ -1602,6 +1608,15 @@ class ClientHttp2Session extends Http2Session {
16021608

16031609
this[kUpdateTimer]();
16041610

1611+
if (headers !== null && headers !== undefined) {
1612+
for (const header of ObjectKeys(headers)) {
1613+
if (header[0] === ':') {
1614+
assertValidPseudoHeader(header);
1615+
} else if (header && !checkIsHttpToken(header))
1616+
this.destroy(new ERR_INVALID_HTTP_TOKEN('Header name', header));
1617+
}
1618+
}
1619+
16051620
assertIsObject(headers, 'headers');
16061621
assertIsObject(options, 'options');
16071622

Collapse file

‎lib/internal/http2/util.js‎

Copy file name to clipboardExpand all lines: lib/internal/http2/util.js
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,7 @@ function sessionName(type) {
595595

596596
module.exports = {
597597
assertIsObject,
598+
assertValidPseudoHeader,
598599
assertValidPseudoHeaderResponse,
599600
assertValidPseudoHeaderTrailer,
600601
assertWithinRange,
Collapse file
+55Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
'use strict';
2+
const common = require('../common');
3+
if (!common.hasCrypto) { common.skip('missing crypto'); }
4+
const assert = require('assert');
5+
const http2 = require('http2');
6+
7+
const server1 = http2.createServer();
8+
9+
server1.listen(0, common.mustCall(() => {
10+
const session = http2.connect(`http://localhost:${server1.address().port}`);
11+
// Check for req headers
12+
session.request({ 'no underscore': 123 });
13+
session.on('error', common.mustCall((e) => {
14+
assert.strictEqual(e.code, 'ERR_INVALID_HTTP_TOKEN');
15+
server1.close();
16+
}));
17+
}));
18+
19+
const server2 = http2.createServer(common.mustCall((req, res) => {
20+
// check for setHeader
21+
res.setHeader('x y z', 123);
22+
res.end();
23+
}));
24+
25+
server2.listen(0, common.mustCall(() => {
26+
const session = http2.connect(`http://localhost:${server2.address().port}`);
27+
const req = session.request();
28+
req.on('error', common.mustCall((e) => {
29+
assert.strictEqual(e.code, 'ERR_HTTP2_STREAM_ERROR');
30+
session.close();
31+
server2.close();
32+
}));
33+
}));
34+
35+
const server3 = http2.createServer(common.mustCall((req, res) => {
36+
// check for writeHead
37+
assert.throws(common.mustCall(() => {
38+
res.writeHead(200, {
39+
'an invalid header': 123
40+
});
41+
}), {
42+
code: 'ERR_HTTP2_INVALID_STREAM'
43+
});
44+
res.end();
45+
}));
46+
47+
server3.listen(0, common.mustCall(() => {
48+
const session = http2.connect(`http://localhost:${server3.address().port}`);
49+
const req = session.request();
50+
req.on('error', common.mustCall((e) => {
51+
assert.strictEqual(e.code, 'ERR_HTTP2_STREAM_ERROR');
52+
server3.close();
53+
session.close();
54+
}));
55+
}));

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.