Moderate severityNVD Advisory· Published Feb 24, 2025· Updated Feb 24, 2025
CVE-2025-26803
CVE-2025-26803
Description
The http parser in Phusion Passenger 6.0.21 through 6.0.25 before 6.0.26 allows a denial of service during parsing of a request with an invalid HTTP method.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
passengerRubyGems | >= 6.0.21, < 6.0.26 | 6.0.26 |
Affected products
1Patches
13 files changed · +46 −23
CHANGELOG+1 −1 modified@@ -1,6 +1,6 @@ Release 6.0.26 (Not yet released) ------------- - * + * [CVE-2025-26803] The http parser (from Passenger 6.0.21-6.0.25) was susceptible to a denial of service attack when parsing a request with an invalid HTTP method. Release 6.0.25
src/cxx_supportlib/ServerKit/HttpHeaderParser.h+19 −21 modified@@ -119,31 +119,26 @@ class HttpHeaderParser { } static size_t http_parser_execute_and_handle_pause(llhttp_t *parser, - const char *data, size_t len, bool &paused) + const char *data, size_t len) { llhttp_errno_t rc = llhttp_get_errno(parser); switch (rc) { case HPE_PAUSED_UPGRADE: llhttp_resume_after_upgrade(parser); + rc = llhttp_get_errno(parser); goto happy_path; case HPE_PAUSED: llhttp_resume(parser); + rc = llhttp_get_errno(parser); goto happy_path; case HPE_OK: + rc = llhttp_execute(parser, data, len); happy_path: - switch (llhttp_execute(parser, data, len)) { - case HPE_PAUSED_H2_UPGRADE: - case HPE_PAUSED_UPGRADE: - case HPE_PAUSED: - paused = true; - return (llhttp_get_error_pos(parser) - data); - case HPE_OK: + if (rc == HPE_OK) { return len; - default: - goto error_path; - } + } + // deliberate fall through default: - error_path: return (llhttp_get_error_pos(parser) - data); } } @@ -488,20 +483,22 @@ class HttpHeaderParser { TRACE_POINT(); P_ASSERT_EQ(message->httpState, Message::PARSING_HEADERS); - size_t ret; - bool paused; - state->parser.data = this; currentBuffer = &buffer; - ret = http_parser_execute_and_handle_pause(&state->parser, - buffer.start, buffer.size(), paused); + size_t ret = http_parser_execute_and_handle_pause(&state->parser, + buffer.start, buffer.size()); currentBuffer = NULL; - if (!llhttp_get_upgrade(&state->parser) && ret != buffer.size() && !paused || !paused && llhttp_get_errno(&state->parser) != HPE_OK) { + llhttp_errno_t llerrno = llhttp_get_errno(&state->parser); + + bool paused = (llerrno == HPE_PAUSED_H2_UPGRADE || llerrno == HPE_PAUSED_UPGRADE || llerrno == HPE_PAUSED); + + if ( (!llhttp_get_upgrade(&state->parser) && ret != buffer.size() && !paused) || + (llerrno != HPE_OK && !paused) ) { UPDATE_TRACE_POINT(); message->httpState = Message::ERROR; - switch (llhttp_get_errno(&state->parser)) { - case HPE_CB_HEADER_FIELD_COMPLETE://?? does this match was HPE_CB_header_field in old one + switch (llerrno) { + case HPE_CB_HEADER_FIELD_COMPLETE:// does this match? was HPE_CB_header_field in old impl case HPE_CB_HEADERS_COMPLETE: switch (state->state) { case HttpHeaderParserState::ERROR_SECURITY_PASSWORD_MISMATCH: @@ -526,9 +523,10 @@ class HttpHeaderParser { break; default: default_error: - message->aux.parseError = HTTP_PARSER_ERRNO_BEGIN - llhttp_get_errno(&state->parser); + message->aux.parseError = HTTP_PARSER_ERRNO_BEGIN - llerrno; break; } + llhttp_finish(&state->parser); } else if (messageHttpStateIndicatesCompletion(MessageType())) { UPDATE_TRACE_POINT(); message->httpMajor = llhttp_get_http_major(&state->parser);
test/cxx/ServerKit/HttpServerTest.cpp+26 −1 modified@@ -806,6 +806,32 @@ namespace tut { "hello /"); } + TEST_METHOD(19) { + set_test_name("It responds with correct error if http method is not recognized"); + + // send invalid request + connectToServer(); + sendRequest("BAD_METHOD / HTTP/1.1\r\n" + "Connection: close\r\n" + "Host: foo\r\n\r\n"); + string response = readAll(fd, 1024).first; + + ensure("Response starts with error", + startsWith(response, + "HTTP/1.0 400 Bad Request\r\n" + "Status: 400 Bad Request\r\n" + "Content-Type: text/html; charset=UTF-8\r\n")); + + ensure("Response ends with error", + endsWith(response, + "Connection: close\r\n" + "Content-Length: 19\r\n" + "cache-control: no-cache, no-store, must-revalidate\r\n" + "\r\n" + "invalid HTTP method")); + ensure_equals("Response size is correct", response.size(), 242u); + } + /***** Fixed body handling *****/ TEST_METHOD(20) { @@ -1477,7 +1503,6 @@ namespace tut { ensure("(1)", containsSubstring(response, "HTTP/1.1 400 Bad Request\r\n")); } - /***** Secure headers handling *****/ TEST_METHOD(60) {
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
9- github.com/advisories/GHSA-2cj2-qqxj-5m3rghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2025-26803ghsaADVISORY
- blog.phusion.nl/2025/02/19/passenger-6-0-26ghsaWEB
- github.com/phusion/passenger/commit/bb15591646687064ab2d578d5f9660b2a4168017ghsaWEB
- github.com/phusion/passenger/compare/release-6.0.25...release-6.0.26ghsaWEB
- github.com/phusion/passenger/releases/tag/release-6.0.26ghsaWEB
- github.com/rubysec/ruby-advisory-db/blob/master/gems/passenger/CVE-2025-26803.ymlghsaWEB
- www.phusionpassenger.com/supportghsaWEB
- blog.phusion.nl/2025/02/19/passenger-6-0-26/mitre
News mentions
0No linked articles in our index yet.