@@ -15,6 +15,7 @@ const {
1515} = primordials ;
1616
1717const {
18+ _checkInvalidHeaderChar : checkInvalidHeaderChar ,
1819 _checkIsHttpToken : checkIsHttpToken ,
1920} = require ( 'internal/http/common' ) ;
2021
@@ -26,11 +27,13 @@ const {
2627 ERR_HTTP2_CONNECT_SCHEME ,
2728 ERR_HTTP2_HEADER_SINGLE_VALUE ,
2829 ERR_HTTP2_INVALID_CONNECTION_HEADERS ,
30+ ERR_HTTP2_INVALID_HEADER_VALUE ,
2931 ERR_HTTP2_INVALID_PSEUDOHEADER : { HideStackFramesError : ERR_HTTP2_INVALID_PSEUDOHEADER } ,
3032 ERR_HTTP2_INVALID_SETTING_VALUE ,
3133 ERR_HTTP2_TOO_MANY_CUSTOM_SETTINGS ,
3234 ERR_INVALID_ARG_TYPE ,
3335 ERR_INVALID_HTTP_TOKEN ,
36+ ERR_UNESCAPED_CHARACTERS ,
3437 } ,
3538 getMessage,
3639 hideStackFrames,
@@ -42,6 +45,7 @@ const kAutoEmptyTrailers = Symbol('autoEmptyTrailers');
4245const kDisableAutoTrailers = Symbol ( 'disableAutoTrailers' ) ;
4346const kSensitiveHeaders = Symbol ( 'sensitiveHeaders' ) ;
4447const kStrictSingleValueFields = Symbol ( 'strictSingleValueFields' ) ;
48+ const kHttpValidation = Symbol ( 'httpValidation' ) ;
4549const kSocket = Symbol ( 'socket' ) ;
4650const kProtocol = Symbol ( 'protocol' ) ;
4751const kProxySocket = Symbol ( 'proxySocket' ) ;
@@ -122,6 +126,23 @@ const kValidPseudoHeaders = new SafeSet([
122126 HTTP2_HEADER_PROTOCOL ,
123127] ) ;
124128
129+ const INVALID_PATH_REGEX = / [ ^ \u0021 - \u00ff ] / ;
130+
131+ function assertValidHeaderValue ( name , value , httpValidation ) {
132+ if ( name === ':path' && INVALID_PATH_REGEX . test ( value ) ) {
133+ throw new ERR_UNESCAPED_CHARACTERS ( 'Request path' ) ;
134+ }
135+
136+ if ( httpValidation === 'insecure' ) {
137+ return ;
138+ }
139+
140+ const lenient = httpValidation === 'relaxed' ;
141+ if ( checkInvalidHeaderChar ( value , lenient ) ) {
142+ throw new ERR_HTTP2_INVALID_HEADER_VALUE ( value , name ) ;
143+ }
144+ }
145+
125146// This set contains headers that are permitted to have only a single
126147// value. Multiple instances must not be specified.
127148const kSingleValueFields = new SafeSet ( [
@@ -700,6 +721,7 @@ function prepareRequestHeadersArray(headers, session) {
700721 rawHeaders ,
701722 assertValidPseudoHeader ,
702723 session [ kStrictSingleValueFields ] ,
724+ session [ kHttpValidation ] ?? 'strict' ,
703725 ) ;
704726
705727 return {
@@ -745,6 +767,7 @@ function prepareRequestHeadersObject(headers, session) {
745767 headersObject ,
746768 assertValidPseudoHeader ,
747769 session [ kStrictSingleValueFields ] ,
770+ session [ kHttpValidation ] ?? 'strict' ,
748771 ) ;
749772
750773 return {
@@ -773,7 +796,9 @@ const kNoHeaderFlags = StringFromCharCode(NGHTTP2_NV_FLAG_NONE);
773796 */
774797function buildNgHeaderString ( arrayOrMap ,
775798 validatePseudoHeaderValue ,
776- strictSingleValueFields ) {
799+ strictSingleValueFields ,
800+ httpValidation ) {
801+ const validateHeaderValues = httpValidation !== undefined ;
777802 let headers = '' ;
778803 let pseudoHeaders = '' ;
779804 let count = 0 ;
@@ -820,6 +845,8 @@ function buildNgHeaderString(arrayOrMap,
820845 const err = validatePseudoHeaderValue ( key ) ;
821846 if ( err !== undefined )
822847 throw err ;
848+ if ( validateHeaderValues )
849+ assertValidHeaderValue ( key , value , httpValidation ) ;
823850 pseudoHeaders += `${ key } \0${ value } \0${ flags } ` ;
824851 count ++ ;
825852 return ;
@@ -837,11 +864,15 @@ function buildNgHeaderString(arrayOrMap,
837864 if ( isArray ) {
838865 for ( let j = 0 ; j < value . length ; ++ j ) {
839866 const val = String ( value [ j ] ) ;
867+ if ( validateHeaderValues )
868+ assertValidHeaderValue ( key , val , httpValidation ) ;
840869 headers += `${ key } \0${ val } \0${ flags } ` ;
841870 }
842871 count += value . length ;
843872 return ;
844873 }
874+ if ( validateHeaderValues )
875+ assertValidHeaderValue ( key , value , httpValidation ) ;
845876 headers += `${ key } \0${ value } \0${ flags } ` ;
846877 count ++ ;
847878 }
@@ -1002,6 +1033,7 @@ module.exports = {
10021033 kAutoEmptyTrailers,
10031034 kDisableAutoTrailers,
10041035 kSensitiveHeaders,
1036+ kHttpValidation,
10051037 kStrictSingleValueFields,
10061038 kSocket,
10071039 kProtocol,
0 commit comments