From 4140690dad7cb77e85ad64a7653e7965971f01e6 Mon Sep 17 00:00:00 2001 From: Eirik Botten Nicolaysen Date: Mon, 31 Aug 2026 10:53:30 +0200 Subject: [PATCH] Reject the empty header field name `validateFieldNames` checks each name with `allSatisfy`, which is true for an empty collection, so a request carrying an empty field name passed validation. RFC 9110 defines `field-name = token` and `token = 1*tchar`. Guard on the empty name before the character check. --- Sources/AsyncHTTPClient/RequestValidation.swift | 5 +++++ .../RequestValidationTests.swift | 13 +++++++++++++ 2 files changed, 18 insertions(+) diff --git a/Sources/AsyncHTTPClient/RequestValidation.swift b/Sources/AsyncHTTPClient/RequestValidation.swift index f338e06a9..a8bbb8fc6 100644 --- a/Sources/AsyncHTTPClient/RequestValidation.swift +++ b/Sources/AsyncHTTPClient/RequestValidation.swift @@ -47,6 +47,11 @@ extension HTTPHeaders { private func validateFieldNames() throws { let invalidFieldNames = self.compactMap { name, _ -> String? in + // [RFC 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-field-names) defines + // `field-name = token`, and `token = 1*tchar`, so a field name must contain at least + // one character. `allSatisfy` alone is true for the empty name. + guard !name.isEmpty else { return name } + let satisfy = name.utf8.allSatisfy { char -> Bool in switch char { case UInt8(ascii: "a")...UInt8(ascii: "z"), diff --git a/Tests/AsyncHTTPClientTests/RequestValidationTests.swift b/Tests/AsyncHTTPClientTests/RequestValidationTests.swift index ea5a6bd66..37fa3e0eb 100644 --- a/Tests/AsyncHTTPClientTests/RequestValidationTests.swift +++ b/Tests/AsyncHTTPClientTests/RequestValidationTests.swift @@ -82,6 +82,19 @@ class RequestValidationTests: XCTestCase { } } + func testEmptyHeaderFieldNameIsRejected() { + // RFC 9110 defines `field-name = token` and `token = 1*tchar`, so the empty + // name is not a valid field name. + var headers = HTTPHeaders([ + ("", "Haha") + ]) + + XCTAssertThrowsError(try headers.validateAndSetTransportFraming(method: .GET, bodyLength: .known(0))) { + error in + XCTAssertEqual(error as? HTTPClientError, HTTPClientError.invalidHeaderFieldNames([""])) + } + } + func testValidHeaderFieldNames() { var headers = HTTPHeaders([ ("abcdefghijklmnopqrstuvwxyz", "Haha"),