From ebfb5d982de56d8bbc87db8448e8d35a883202d3 Mon Sep 17 00:00:00 2001 From: Paolo Insogna Date: Tue, 29 Oct 2024 09:29:50 +0000 Subject: [PATCH] fix: Do not allow OBS fold in headers by default. Upstream backport: https://github.com/nodejs/llhttp/pull/348 --- src/llhttp/http.ts | 13 +++-- test/request/connection.md | 4 +- test/request/invalid.md | 85 ++++++++++++++++++++++++++++++ test/request/sample.md | 2 +- test/request/transfer-encoding.md | 2 +- test/response/transfer-encoding.md | 2 +- 6 files changed, 98 insertions(+), 10 deletions(-) diff --git a/src/llhttp/http.ts b/src/llhttp/http.ts index d0bfd48..40eff4c 100644 --- a/src/llhttp/http.ts +++ b/src/llhttp/http.ts @@ -827,11 +827,14 @@ export class HTTP { 'Missing expected LF after header value')); n('header_value_lws') - .peek([ ' ', '\t' ], - this.load('header_state', { - [HEADER_STATE.TRANSFER_ENCODING_CHUNKED]: - this.resetHeaderState(span.headerValue.start(n('header_value_start'))), - }, span.headerValue.start(n('header_value_start')))) + .peek( + [ ' ', '\t' ], + this.testLenientFlags(LENIENT_FLAGS.HEADERS, { + 1: this.load('header_state', { + [HEADER_STATE.TRANSFER_ENCODING_CHUNKED]: + this.resetHeaderState(span.headerValue.start(n('header_value_start'))), + }, span.headerValue.start(n('header_value_start'))), + }, p.error(ERROR.INVALID_HEADER_TOKEN, 'Unexpected whitespace after header value'))) .otherwise(this.setHeaderFlags(onHeaderValueComplete)); const checkTrailing = this.testFlags(FLAGS.TRAILING, { diff --git a/test/request/connection.md b/test/request/connection.md index a03242e..68ed3e0 100644 --- a/test/request/connection.md +++ b/test/request/connection.md @@ -374,7 +374,7 @@ off=75 message complete ### Multiple tokens with folding - + ```http GET /demo HTTP/1.1 Host: example.com @@ -465,7 +465,7 @@ off=75 error code=22 reason="Pause on CONNECT/Upgrade" ### Multiple tokens with folding, LWS, and CRLF - + ```http GET /demo HTTP/1.1 Connection: keep-alive, \r\n upgrade diff --git a/test/request/invalid.md b/test/request/invalid.md index 8eadacf..0d3b36e 100644 --- a/test/request/invalid.md +++ b/test/request/invalid.md @@ -583,4 +583,89 @@ off=122 len=3 span[header_value]="ghi" off=126 header_value complete off=127 chunk complete off=127 message complete +``` + +### Spaces before headers + + + +```http +POST /hello HTTP/1.1 +Host: localhost +Foo: bar + Content-Length: 38 + +GET /bye HTTP/1.1 +Host: localhost + + +``` + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=6 span[url]="/hello" +off=12 url complete +off=17 len=3 span[version]="1.1" +off=20 version complete +off=22 len=4 span[header_field]="Host" +off=27 header_field complete +off=28 len=9 span[header_value]="localhost" +off=39 header_value complete +off=39 len=3 span[header_field]="Foo" +off=43 header_field complete +off=44 len=3 span[header_value]="bar" +off=49 error code=10 reason="Unexpected whitespace after header value" +``` + +### Spaces before headers (lenient) + + + +```http +POST /hello HTTP/1.1 +Host: localhost +Foo: bar + Content-Length: 38 + +GET /bye HTTP/1.1 +Host: localhost + + +``` + +```log +off=0 message begin +off=0 len=4 span[method]="POST" +off=4 method complete +off=5 len=6 span[url]="/hello" +off=12 url complete +off=17 len=3 span[version]="1.1" +off=20 version complete +off=22 len=4 span[header_field]="Host" +off=27 header_field complete +off=28 len=9 span[header_value]="localhost" +off=39 header_value complete +off=39 len=3 span[header_field]="Foo" +off=43 header_field complete +off=44 len=3 span[header_value]="bar" +off=49 len=19 span[header_value]=" Content-Length: 38" +off=70 header_value complete +off=72 headers complete method=3 v=1/1 flags=0 content_length=0 +off=72 message complete +off=72 reset +off=72 message begin +off=72 len=3 span[method]="GET" +off=75 method complete +off=76 len=4 span[url]="/bye" +off=81 url complete +off=86 len=3 span[version]="1.1" +off=89 version complete +off=91 len=4 span[header_field]="Host" +off=96 header_field complete +off=97 len=9 span[header_value]="localhost" +off=108 header_value complete +off=110 headers complete method=1 v=1/1 flags=0 content_length=0 +off=110 message complete ``` \ No newline at end of file diff --git a/test/request/sample.md b/test/request/sample.md index f0a5d44..de2ceb9 100644 --- a/test/request/sample.md +++ b/test/request/sample.md @@ -540,7 +540,7 @@ off=61 message complete See nodejs/test/parallel/test-http-headers-obstext.js - + ```http GET / HTTP/1.1 X-SSL-Nonsense: -----BEGIN CERTIFICATE----- diff --git a/test/request/transfer-encoding.md b/test/request/transfer-encoding.md index 0f839bc..b1b523d 100644 --- a/test/request/transfer-encoding.md +++ b/test/request/transfer-encoding.md @@ -893,7 +893,7 @@ off=51 error code=12 reason="Invalid character in chunk size" ## Invalid OBS fold after chunked value - + ```http PUT /url HTTP/1.1 Transfer-Encoding: chunked diff --git a/test/response/transfer-encoding.md b/test/response/transfer-encoding.md index e1fd10a..0f54c72 100644 --- a/test/response/transfer-encoding.md +++ b/test/response/transfer-encoding.md @@ -370,7 +370,7 @@ off=101 error code=2 reason="Invalid character in chunk extensions quoted value" ## Invalid OBS fold after chunked value - + ```http HTTP/1.1 200 OK Transfer-Encoding: chunked -- 2.47.0