File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -10,6 +10,7 @@ const {
1010 RequestContentLengthMismatchError,
1111 ResponseContentLengthMismatchError,
1212 RequestAbortedError,
13+ InvalidArgumentError,
1314 HeadersTimeoutError,
1415 HeadersOverflowError,
1516 SocketError,
@@ -1134,8 +1135,16 @@ function writeH1 (client, request) {
11341135 }
11351136 body = bodyStream . stream
11361137 contentLength = bodyStream . length
1137- } else if ( util . isBlobLike ( body ) && request . contentType == null && body . type ) {
1138- headers . push ( 'content-type' , body . type )
1138+ } else if ( util . isBlobLike ( body ) && request . contentType == null ) {
1139+ const contentType = body . type
1140+ if ( contentType ) {
1141+ const contentTypeValue = `${ contentType } `
1142+ if ( ! util . isValidHeaderValue ( contentTypeValue ) ) {
1143+ util . errorRequest ( client , request , new InvalidArgumentError ( 'invalid content-type header' ) )
1144+ return false
1145+ }
1146+ headers . push ( 'content-type' , contentTypeValue )
1147+ }
11391148 }
11401149
11411150 if ( body && typeof body . read === 'function' ) {
Original file line number Diff line number Diff line change 11'use strict'
22
3+ const assert = require ( 'node:assert' )
34const { tspl } = require ( '@matteo.collina/tspl' )
45const { createServer } = require ( 'node:http' )
56const { test, after } = require ( 'node:test' )
@@ -34,3 +35,33 @@ test('should validate content-type CRLF Injection', async (t) => {
3435 }
3536 await t . completed
3637} )
38+
39+ test ( 'should validate blob body content-type CRLF Injection' , async ( ) => {
40+ let receivedRequest = false
41+ const server = createServer ( { joinDuplicateHeaders : true } , ( req , res ) => {
42+ receivedRequest = true
43+ res . statusCode = 200
44+ res . end ( 'hello' )
45+ } )
46+
47+ after ( ( ) => server . close ( ) )
48+
49+ server . listen ( 0 )
50+
51+ await once ( server , 'listening' )
52+
53+ class MaliciousBlob extends Blob {
54+ get type ( ) {
55+ return 'text/html\r\nX-Injected: true'
56+ }
57+ }
58+
59+ await assert . rejects (
60+ request ( `http://localhost:${ server . address ( ) . port } /endpoint` , {
61+ method : 'POST' ,
62+ body : new MaliciousBlob ( [ 'hello' ] )
63+ } ) ,
64+ ( e ) => e instanceof errors . InvalidArgumentError && e . message === 'invalid content-type header'
65+ )
66+ assert . strictEqual ( receivedRequest , false )
67+ } )
You can’t perform that action at this time.
0 commit comments