diff --git a/lib/internal/http2/compat.js b/lib/internal/http2/compat.js
index 3abe9ba2ac6f82..e1788215c67fb2 100644
--- a/lib/internal/http2/compat.js
+++ b/lib/internal/http2/compat.js
@@ -40,6 +40,7 @@ const {
ERR_HTTP2_STATUS_INVALID,
ERR_INVALID_ARG_VALUE,
ERR_INVALID_CALLBACK,
+ ERR_INVALID_CHAR,
ERR_INVALID_HTTP_TOKEN,
ERR_STREAM_WRITE_AFTER_END
},
@@ -47,6 +48,10 @@ const {
} = require('internal/errors');
const { validateString } = require('internal/validators');
const { kSocket, kRequest, kProxySocket } = require('internal/http2/util');
+const { _checkIsHttpToken: checkIsHttpToken,
+ _checkInvalidHeaderChar: checkInvalidHeaderChar
+} = require('_http_common');
+const debug = require('internal/util/debuglog').debuglog('http2');
const kBeginSend = Symbol('begin-send');
const kState = Symbol('state');
@@ -67,15 +72,19 @@ let statusConnectionHeaderWarned = false;
// close as possible to the current require('http') API
const assertValidHeader = hideStackFrames((name, value) => {
- if (name === '' || typeof name !== 'string') {
- throw new ERR_INVALID_HTTP_TOKEN('Header name', name);
- }
if (isPseudoHeader(name)) {
throw new ERR_HTTP2_PSEUDOHEADER_NOT_ALLOWED();
}
+ if (name === '' || typeof name !== 'string' || !checkIsHttpToken(name)) {
+ throw new ERR_INVALID_HTTP_TOKEN('Header name', name);
+ }
if (value === undefined || value === null) {
throw new ERR_HTTP2_INVALID_HEADER_VALUE(value, name);
}
+ if (checkInvalidHeaderChar(value)) {
+ debug('Header "%s" contains invalid characters', name);
+ throw new ERR_INVALID_CHAR('header content', name);
+ }
if (!isConnectionHeaderAllowed(name, value)) {
connectionHeaderMessageWarn();
}
diff --git a/test/parallel/test-http2-invalid-headers.js b/test/parallel/test-http2-invalid-headers.js
new file mode 100644
index 00000000000000..e0324a93051568
--- /dev/null
+++ b/test/parallel/test-http2-invalid-headers.js
@@ -0,0 +1,32 @@
+'use strict';
+const common = require('../common');
+if (!common.hasCrypto) { common.skip('missing crypto'); }
+const h2 = require('http2');
+const assert = require('assert');
+
+const server = h2.createServer(common.mustCall((req, res) => {
+ assert.throws(() => {
+ res.setHeader('foo⠊Set-Cookie', 'foo=bar');
+ }, { code: 'ERR_INVALID_HTTP_TOKEN' });
+ assert.throws(() => {
+ res.writeHead(200, { 'foo⠊Set-Cookie': 'foo=bar' });
+ }, { code: 'ERR_INVALID_HTTP_TOKEN' });
+ assert.throws(() => {
+ res.setHeader('Set-Cookie', 'foo=barഊഊ');
+ }, { code: 'ERR_INVALID_CHAR' });
+ assert.throws(() => {
+ res.writeHead(200, {
+ 'Set-Cookie': 'foo=barഊഊ'
+ });
+ }, { code: 'ERR_INVALID_CHAR' });
+ res.end();
+}));
+
+server.listen(0, common.mustCall(() => {
+ const session = h2.connect(`http://localhost:${server.address().port}`);
+ const req = session.request();
+ req.on('end', () => {
+ session.close();
+ server.close();
+ });
+}));