VYPR
Moderate severityNVD Advisory· Published Oct 5, 2023· Updated Sep 19, 2024

Incorrect request error handling triggers server crash in Vapor

CVE-2023-44386

Description

Vapor HTTP web framework versions prior to 4.84.2 are vulnerable to a denial of service attack due to mishandling of HTTP 1.x parse errors, causing server crash.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Vapor HTTP web framework versions prior to 4.84.2 are vulnerable to a denial of service attack due to mishandling of HTTP 1.x parse errors, causing server crash.

Vulnerability

Vapor, a Swift HTTP web framework, contains a denial of service vulnerability in its HTTP1 error handler. Instead of forwarding HTTP parsing errors through the pipeline, the handler closes the connection, which triggers a precondition failure in swift-nio and crashes the server [1][2][3].

Exploitation

An attacker can exploit this by sending a malformed HTTP 1.x request to any Vapor server running an affected version. No authentication or special network position is required; the request is simply parsed and the error causes the handler to misbehave [3].

Impact

The vulnerability results in immediate termination of the server process, causing a denial of service. There is no risk of data leakage or unauthorized code execution, as the crash is an explicit assertion failure. Service can be restored by restarting the server [3].

Mitigation

The issue is fixed in Vapor release 4.84.2. Users should upgrade to this version or later. No workarounds are available [1][3].

AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
github.com/vapor/vaporSwiftURL
>= 4.83.2, < 4.84.24.84.2

Affected products

2

Patches

1
090464a654b0

Merge pull request from GHSA-3mwq-h3g6-ffhm

https://github.com/vapor/vaporGwynne RaskindOct 5, 2023via ghsa
4 files changed · +6 73
  • Sources/Vapor/HTTP/Server/HTTPServerHandler.swift+1 1 modified
    @@ -71,7 +71,7 @@ final class HTTPServerHandler: ChannelInboundHandler, RemovableChannelHandler {
                 self.logger.trace("HTTP handler will no longer respect keep-alive")
                 self.isShuttingDown = true
             default:
    -            self.logger.trace("Unhandled user event: \(event)")
    +            context.fireUserInboundEventTriggered(event)
             }
         }
     }
    
  • Sources/Vapor/HTTP/Server/HTTPServerRequestDecoder.swift+5 1 modified
    @@ -133,6 +133,10 @@ final class HTTPServerRequestDecoder: ChannelDuplexHandler, RemovableChannelHand
             default:
                 break
             }
    +
    +        if error is HTTPParserError {
    +            self.logger.debug("Invalid HTTP request, will close connection: \(String(reflecting: error))")
    +        }
             context.fireErrorCaught(error)
         }
     
    @@ -218,7 +222,7 @@ final class HTTPServerRequestDecoder: ChannelDuplexHandler, RemovableChannelHand
                     context.fireUserInboundEventTriggered(event)
                 }
             default:
    -            self.logger.trace("Unhandled user event: \(event)")
    +            context.fireUserInboundEventTriggered(event)
             }
         }
     }
    
  • Sources/Vapor/HTTP/Server/HTTPServer.swift+0 70 modified
    @@ -452,73 +452,6 @@ private final class HTTPServerConnection: Sendable {
         }
     }
     
    -/// A simple channel handler that catches errors emitted by parsing HTTP requests
    -/// and sends 400 Bad Request responses.
    -///
    -/// This channel handler provides the basic behaviour that the majority of simple HTTP
    -/// servers want. This handler does not suppress the parser errors: it allows them to
    -/// continue to pass through the pipeline so that other handlers (e.g. logging ones) can
    -/// deal with the error.
    -/// 
    -/// adapted from: https://github.com/apple/swift-nio/blob/00341c92770e0a7bebdc5fda783f08765eb3ff56/Sources/NIOHTTP1/HTTPServerProtocolErrorHandler.swift
    -final class HTTP1ServerErrorHandler: ChannelDuplexHandler, RemovableChannelHandler {
    -    typealias InboundIn = Never
    -    typealias InboundOut = Never
    -    typealias OutboundIn = HTTPServerResponsePart
    -    typealias OutboundOut = HTTPServerResponsePart
    -    let logger: Logger
    -    private var hasUnterminatedResponse: Bool = false
    -    
    -    init(logger: Logger) {
    -        self.logger = logger
    -    }
    -    
    -    func errorCaught(context: ChannelHandlerContext, error: Error) {
    -        if let error = error as? HTTPParserError {
    -            self.makeHTTPParserErrorResponse(context: context, error: error)
    -        }
    -
    -        // Now pass the error on in case someone else wants to see it.
    -        // In the Vapor ChannelPipeline the connection will eventually 
    -        // be closed by the NIOCloseOnErrorHandler
    -        context.fireErrorCaught(error)
    -    }
    -
    -    private func makeHTTPParserErrorResponse(context: ChannelHandlerContext, error: HTTPParserError) {
    -        // Any HTTPParserError is automatically fatal, and we don't actually need (or want) to
    -        // provide that error to the client: we just want to inform them something went wrong
    -        // and then close off the pipeline. However, we can only send an
    -        // HTTP error response if another response hasn't started yet.
    -        //
    -        // A side note here: we cannot block or do any delayed work. 
    -        // The channel might be closed right after we return from this function.
    -        if !self.hasUnterminatedResponse {
    -            self.logger.debug("Bad Request - Invalid HTTP: \(error)")
    -            let headers = HTTPHeaders([("Connection", "close"), ("Content-Length", "0")])
    -            let head = HTTPResponseHead(version: .http1_1, status: .badRequest, headers: headers)
    -            context.write(self.wrapOutboundOut(.head(head)), promise: nil)
    -            context.writeAndFlush(self.wrapOutboundOut(.end(nil)), promise: nil)
    -        }
    -    }
    -
    -    public func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {
    -        let res = self.unwrapOutboundIn(data)
    -        switch res {
    -        case .head(let head) where head.isInformational:
    -            precondition(!self.hasUnterminatedResponse)
    -        case .head:
    -            precondition(!self.hasUnterminatedResponse)
    -            self.hasUnterminatedResponse = true
    -        case .body:
    -            precondition(self.hasUnterminatedResponse)
    -        case .end:
    -            precondition(self.hasUnterminatedResponse)
    -            self.hasUnterminatedResponse = false
    -        }
    -        context.write(data, promise: promise)
    -    }
    -}
    -
     extension HTTPResponseHead {
         /// Determines if the head is purely informational. If a head is informational another head will follow this
         /// head eventually.
    @@ -608,9 +541,6 @@ extension ChannelPipeline {
                 break
             }
     
    -        let errorHandler = HTTP1ServerErrorHandler(logger: configuration.logger)
    -        handlers.append(errorHandler)
    -
             // add NIO -> HTTP response encoder
             let serverResEncoder = HTTPServerResponseEncoder(
                 serverHeader: configuration.serverName,
    
  • Tests/VaporTests/PipelineTests.swift+0 1 modified
    @@ -138,7 +138,6 @@ final class PipelineTests: XCTestCase {
                 }
             }
             XCTAssertEqual(channel.isActive, false)
    -        try XCTAssertContains(channel.readOutbound(as: ByteBuffer.self)?.string, "HTTP/1.1 400 Bad Request")
             try XCTAssertNil(channel.readOutbound(as: ByteBuffer.self)?.string)
         }
     
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.