VYPR
Low severityNVD Advisory· Published Oct 12, 2021· Updated May 27, 2025

Inconsistent Interpretation of HTTP Requests ('HTTP Request Smuggling') in puma

CVE-2021-41136

Description

Puma is a HTTP 1.1 server for Ruby/Rack applications. Prior to versions 5.5.1 and 4.3.9, using puma with a proxy which forwards HTTP header values which contain the LF character could allow HTTP request smugggling. A client could smuggle a request through a proxy, causing the proxy to send a response back to another unknown client. The only proxy which has this behavior, as far as the Puma team is aware of, is Apache Traffic Server. If the proxy uses persistent connections and the client adds another request in via HTTP pipelining, the proxy may mistake it as the first request's body. Puma, however, would see it as two requests, and when processing the second request, send back a response that the proxy does not expect. If the proxy has reused the persistent connection to Puma to send another request for a different client, the second response from the first client will be sent to the second client. This vulnerability was patched in Puma 5.5.1 and 4.3.9. As a workaround, do not use Apache Traffic Server with puma.

AI Insight

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

Puma HTTP server prior to 5.5.1 and 4.3.9 allows request smuggling when used behind Apache Traffic Server due to insufficient handling of LF characters in forwarded headers.

Vulnerability

Puma, a Ruby/Rack HTTP 1.1 server, before versions 5.5.1 and 4.3.9 fails to properly sanitize HTTP header values containing the LF (line feed) character. When puma is deployed behind a proxy such as Apache Traffic Server, the proxy may forward headers with embedded LF characters. This allows an attacker to craft a request that is interpreted differently by the proxy and puma, leading to HTTP request smuggling [1]. The affected versions are all Puma releases prior to 5.5.1 and 4.3.9.

Exploitation

An attacker must have the ability to send HTTP requests through a proxy that forwards header values containing LF characters. According to the Puma team, the only proxy known to exhibit this behavior is Apache Traffic Server [1]. If the proxy uses persistent connections and the client sends multiple requests via HTTP pipelining, the proxy may mistake the smuggled second request as the body of the first request. However, puma treats them as two separate requests. When puma processes the second request, it sends a response that the proxy does not expect. If the proxy has reused the persistent connection to puma for a different client, the second response from the first client is incorrectly forwarded to the second client [1].

Impact

Successful exploitation allows an attacker to smuggle an HTTP request through the proxy, causing the proxy to send the response intended for the smuggled request to an unintended client. This leads to information disclosure, as responses intended for one user are delivered to another user. The compromise occurs at the HTTP response level, potentially exposing sensitive data or enabling session hijacking [1].

Mitigation

The vulnerability is patched in Puma versions 5.5.1 and 4.3.9 [1]. The patches involved changes to the HTTP parser's state machine to reject header values containing LF characters, as seen in commits referencing the fix [2][3][4]. As a workaround, users are advised to avoid using Apache Traffic Server in front of puma [1]. No other mitigations are documented.

AI Insight generated on May 21, 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
pumaRubyGems
>= 5.0.0, < 5.5.15.5.1
pumaRubyGems
< 4.3.94.3.9

Affected products

98

Patches

3
fb6ad8f8013a

4.3.9 (#2721)

https://github.com/puma/pumaNate BerkopecOct 12, 2021via ghsa
6 files changed · +90 48
  • ext/puma_http11/http11_parser.c+19 12 modified
    @@ -428,10 +428,13 @@ case 17:
     case 18:
     #line 428 "ext/puma_http11/http11_parser.c"
     	switch( (*p) ) {
    +		case 9: goto tr25;
     		case 13: goto tr26;
     		case 32: goto tr27;
     	}
    -	goto tr25;
    +	if ( 33 <= (*p) && (*p) <= 126 )
    +		goto tr25;
    +	goto st0;
     tr25:
     #line 44 "ext/puma_http11/http11_parser.rl"
     	{ MARK(mark, p); }
    @@ -440,10 +443,14 @@ case 18:
     	if ( ++p == pe )
     		goto _test_eof19;
     case 19:
    -#line 442 "ext/puma_http11/http11_parser.c"
    -	if ( (*p) == 13 )
    -		goto tr29;
    -	goto st19;
    +#line 445 "ext/puma_http11/http11_parser.c"
    +	switch( (*p) ) {
    +		case 9: goto st19;
    +		case 13: goto tr29;
    +	}
    +	if ( 32 <= (*p) && (*p) <= 126 )
    +		goto st19;
    +	goto st0;
     tr9:
     #line 51 "ext/puma_http11/http11_parser.rl"
     	{
    @@ -486,7 +493,7 @@ case 19:
     	if ( ++p == pe )
     		goto _test_eof20;
     case 20:
    -#line 488 "ext/puma_http11/http11_parser.c"
    +#line 495 "ext/puma_http11/http11_parser.c"
     	switch( (*p) ) {
     		case 32: goto tr31;
     		case 60: goto st0;
    @@ -507,7 +514,7 @@ case 20:
     	if ( ++p == pe )
     		goto _test_eof21;
     case 21:
    -#line 509 "ext/puma_http11/http11_parser.c"
    +#line 516 "ext/puma_http11/http11_parser.c"
     	switch( (*p) ) {
     		case 32: goto tr33;
     		case 60: goto st0;
    @@ -528,7 +535,7 @@ case 21:
     	if ( ++p == pe )
     		goto _test_eof22;
     case 22:
    -#line 530 "ext/puma_http11/http11_parser.c"
    +#line 537 "ext/puma_http11/http11_parser.c"
     	switch( (*p) ) {
     		case 43: goto st22;
     		case 58: goto st23;
    @@ -553,7 +560,7 @@ case 22:
     	if ( ++p == pe )
     		goto _test_eof23;
     case 23:
    -#line 555 "ext/puma_http11/http11_parser.c"
    +#line 562 "ext/puma_http11/http11_parser.c"
     	switch( (*p) ) {
     		case 32: goto tr8;
     		case 34: goto st0;
    @@ -573,7 +580,7 @@ case 23:
     	if ( ++p == pe )
     		goto _test_eof24;
     case 24:
    -#line 575 "ext/puma_http11/http11_parser.c"
    +#line 582 "ext/puma_http11/http11_parser.c"
     	switch( (*p) ) {
     		case 32: goto tr37;
     		case 34: goto st0;
    @@ -596,7 +603,7 @@ case 24:
     	if ( ++p == pe )
     		goto _test_eof25;
     case 25:
    -#line 598 "ext/puma_http11/http11_parser.c"
    +#line 605 "ext/puma_http11/http11_parser.c"
     	switch( (*p) ) {
     		case 32: goto tr41;
     		case 34: goto st0;
    @@ -616,7 +623,7 @@ case 25:
     	if ( ++p == pe )
     		goto _test_eof26;
     case 26:
    -#line 618 "ext/puma_http11/http11_parser.c"
    +#line 625 "ext/puma_http11/http11_parser.c"
     	switch( (*p) ) {
     		case 32: goto tr44;
     		case 34: goto st0;
    
  • ext/puma_http11/http11_parser_common.rl+1 1 modified
    @@ -43,7 +43,7 @@
     
       field_name = ( token -- ":" )+ >start_field $snake_upcase_field %write_field;
     
    -  field_value = any* >start_value %write_value;
    +  field_value = ( print | "\t" )* >start_value %write_value;
     
       message_header = field_name ":" " "* field_value :> CRLF;
     
    
  • ext/puma_http11/org/jruby/puma/Http11Parser.java+34 34 modified
    @@ -34,9 +34,9 @@ private static short[] init__puma_parser_key_offsets_0()
     {
     	return new short [] {
     	    0,    0,    8,   17,   27,   29,   30,   31,   32,   33,   34,   36,
    -	   39,   41,   44,   45,   61,   62,   78,   80,   81,   89,   97,  107,
    -	  115,  124,  132,  140,  149,  158,  167,  176,  185,  194,  203,  212,
    -	  221,  230,  239,  248,  257,  266,  275,  284,  293,  302,  303
    +	   39,   41,   44,   45,   61,   62,   78,   83,   87,   95,  103,  113,
    +	  121,  130,  138,  146,  155,  164,  173,  182,  191,  200,  209,  218,
    +	  227,  236,  245,  254,  263,  272,  281,  290,  299,  308,  309
     	};
     }
     
    @@ -52,14 +52,13 @@ private static char[] init__puma_parser_trans_keys_0()
     	   46,   48,   57,   48,   57,   13,   48,   57,   10,   13,   33,  124,
     	  126,   35,   39,   42,   43,   45,   46,   48,   57,   65,   90,   94,
     	  122,   10,   33,   58,  124,  126,   35,   39,   42,   43,   45,   46,
    -	   48,   57,   65,   90,   94,  122,   13,   32,   13,   32,   60,   62,
    -	  127,    0,   31,   34,   35,   32,   60,   62,  127,    0,   31,   34,
    -	   35,   43,   58,   45,   46,   48,   57,   65,   90,   97,  122,   32,
    -	   34,   35,   60,   62,  127,    0,   31,   32,   34,   35,   60,   62,
    -	   63,  127,    0,   31,   32,   34,   35,   60,   62,  127,    0,   31,
    -	   32,   34,   35,   60,   62,  127,    0,   31,   32,   36,   95,   45,
    -	   46,   48,   57,   65,   90,   32,   36,   95,   45,   46,   48,   57,
    -	   65,   90,   32,   36,   95,   45,   46,   48,   57,   65,   90,   32,
    +	   48,   57,   65,   90,   94,  122,    9,   13,   32,   33,  126,    9,
    +	   13,   32,  126,   32,   60,   62,  127,    0,   31,   34,   35,   32,
    +	   60,   62,  127,    0,   31,   34,   35,   43,   58,   45,   46,   48,
    +	   57,   65,   90,   97,  122,   32,   34,   35,   60,   62,  127,    0,
    +	   31,   32,   34,   35,   60,   62,   63,  127,    0,   31,   32,   34,
    +	   35,   60,   62,  127,    0,   31,   32,   34,   35,   60,   62,  127,
    +	    0,   31,   32,   36,   95,   45,   46,   48,   57,   65,   90,   32,
     	   36,   95,   45,   46,   48,   57,   65,   90,   32,   36,   95,   45,
     	   46,   48,   57,   65,   90,   32,   36,   95,   45,   46,   48,   57,
     	   65,   90,   32,   36,   95,   45,   46,   48,   57,   65,   90,   32,
    @@ -71,7 +70,8 @@ private static char[] init__puma_parser_trans_keys_0()
     	   65,   90,   32,   36,   95,   45,   46,   48,   57,   65,   90,   32,
     	   36,   95,   45,   46,   48,   57,   65,   90,   32,   36,   95,   45,
     	   46,   48,   57,   65,   90,   32,   36,   95,   45,   46,   48,   57,
    -	   65,   90,   32,    0
    +	   65,   90,   32,   36,   95,   45,   46,   48,   57,   65,   90,   32,
    +	   36,   95,   45,   46,   48,   57,   65,   90,   32,    0
     	};
     }
     
    @@ -82,7 +82,7 @@ private static byte[] init__puma_parser_single_lengths_0()
     {
     	return new byte [] {
     	    0,    2,    3,    4,    2,    1,    1,    1,    1,    1,    0,    1,
    -	    0,    1,    1,    4,    1,    4,    2,    1,    4,    4,    2,    6,
    +	    0,    1,    1,    4,    1,    4,    3,    2,    4,    4,    2,    6,
     	    7,    6,    6,    3,    3,    3,    3,    3,    3,    3,    3,    3,
     	    3,    3,    3,    3,    3,    3,    3,    3,    3,    1,    0
     	};
    @@ -95,7 +95,7 @@ private static byte[] init__puma_parser_range_lengths_0()
     {
     	return new byte [] {
     	    0,    3,    3,    3,    0,    0,    0,    0,    0,    0,    1,    1,
    -	    1,    1,    0,    6,    0,    6,    0,    0,    2,    2,    4,    1,
    +	    1,    1,    0,    6,    0,    6,    1,    1,    2,    2,    4,    1,
     	    1,    1,    1,    3,    3,    3,    3,    3,    3,    3,    3,    3,
     	    3,    3,    3,    3,    3,    3,    3,    3,    3,    0,    0
     	};
    @@ -108,9 +108,9 @@ private static short[] init__puma_parser_index_offsets_0()
     {
     	return new short [] {
     	    0,    0,    6,   13,   21,   24,   26,   28,   30,   32,   34,   36,
    -	   39,   41,   44,   46,   57,   59,   70,   73,   75,   82,   89,   96,
    -	  104,  113,  121,  129,  136,  143,  150,  157,  164,  171,  178,  185,
    -	  192,  199,  206,  213,  220,  227,  234,  241,  248,  255,  257
    +	   39,   41,   44,   46,   57,   59,   70,   75,   79,   86,   93,  100,
    +	  108,  117,  125,  133,  140,  147,  154,  161,  168,  175,  182,  189,
    +	  196,  203,  210,  217,  224,  231,  238,  245,  252,  259,  261
     	};
     }
     
    @@ -125,23 +125,23 @@ private static byte[] init__puma_parser_indicies_0()
     	   10,    1,   11,    1,   12,    1,   13,    1,   14,    1,   15,    1,
     	   16,   15,    1,   17,    1,   18,   17,    1,   19,    1,   20,   21,
     	   21,   21,   21,   21,   21,   21,   21,   21,    1,   22,    1,   23,
    -	   24,   23,   23,   23,   23,   23,   23,   23,   23,    1,   26,   27,
    -	   25,   29,   28,   30,    1,    1,    1,    1,    1,   31,   32,    1,
    -	    1,    1,    1,    1,   33,   34,   35,   34,   34,   34,   34,    1,
    -	    8,    1,    9,    1,    1,    1,    1,   35,   36,    1,   38,    1,
    -	    1,   39,    1,    1,   37,   40,    1,   42,    1,    1,    1,    1,
    -	   41,   43,    1,   45,    1,    1,    1,    1,   44,    2,   46,   46,
    -	   46,   46,   46,    1,    2,   47,   47,   47,   47,   47,    1,    2,
    -	   48,   48,   48,   48,   48,    1,    2,   49,   49,   49,   49,   49,
    -	    1,    2,   50,   50,   50,   50,   50,    1,    2,   51,   51,   51,
    -	   51,   51,    1,    2,   52,   52,   52,   52,   52,    1,    2,   53,
    -	   53,   53,   53,   53,    1,    2,   54,   54,   54,   54,   54,    1,
    -	    2,   55,   55,   55,   55,   55,    1,    2,   56,   56,   56,   56,
    -	   56,    1,    2,   57,   57,   57,   57,   57,    1,    2,   58,   58,
    -	   58,   58,   58,    1,    2,   59,   59,   59,   59,   59,    1,    2,
    -	   60,   60,   60,   60,   60,    1,    2,   61,   61,   61,   61,   61,
    -	    1,    2,   62,   62,   62,   62,   62,    1,    2,   63,   63,   63,
    -	   63,   63,    1,    2,    1,    1,    0
    +	   24,   23,   23,   23,   23,   23,   23,   23,   23,    1,   25,   26,
    +	   27,   25,    1,   28,   29,   28,    1,   30,    1,    1,    1,    1,
    +	    1,   31,   32,    1,    1,    1,    1,    1,   33,   34,   35,   34,
    +	   34,   34,   34,    1,    8,    1,    9,    1,    1,    1,    1,   35,
    +	   36,    1,   38,    1,    1,   39,    1,    1,   37,   40,    1,   42,
    +	    1,    1,    1,    1,   41,   43,    1,   45,    1,    1,    1,    1,
    +	   44,    2,   46,   46,   46,   46,   46,    1,    2,   47,   47,   47,
    +	   47,   47,    1,    2,   48,   48,   48,   48,   48,    1,    2,   49,
    +	   49,   49,   49,   49,    1,    2,   50,   50,   50,   50,   50,    1,
    +	    2,   51,   51,   51,   51,   51,    1,    2,   52,   52,   52,   52,
    +	   52,    1,    2,   53,   53,   53,   53,   53,    1,    2,   54,   54,
    +	   54,   54,   54,    1,    2,   55,   55,   55,   55,   55,    1,    2,
    +	   56,   56,   56,   56,   56,    1,    2,   57,   57,   57,   57,   57,
    +	    1,    2,   58,   58,   58,   58,   58,    1,    2,   59,   59,   59,
    +	   59,   59,    1,    2,   60,   60,   60,   60,   60,    1,    2,   61,
    +	   61,   61,   61,   61,    1,    2,   62,   62,   62,   62,   62,    1,
    +	    2,   63,   63,   63,   63,   63,    1,    2,    1,    1,    0
     	};
     }
     
    
  • History.md+5 0 modified
    @@ -1,3 +1,8 @@
    +## 4.3.9 / 2021-10-12
    +
    +* Security
    +  * Do not allow LF as a line ending in a header (CVE-2021-41136)
    +
     ## 4.3.8 / 2021-05-11
     
     * Security
    
  • lib/puma/const.rb+1 1 modified
    @@ -100,7 +100,7 @@ class UnsupportedOption < RuntimeError
       # too taxing on performance.
       module Const
     
    -    PUMA_VERSION = VERSION = "4.3.8".freeze
    +    PUMA_VERSION = VERSION = "4.3.9".freeze
         CODE_NAME = "Mysterious Traveller".freeze
         PUMA_SERVER_STRING = ['puma', PUMA_VERSION, CODE_NAME].join(' ').freeze
     
    
  • test/test_http11.rb+30 0 modified
    @@ -208,4 +208,34 @@ def test_trims_whitespace_from_headers
     
         assert_equal "Strip This", req["HTTP_X_STRIP_ME"]
       end
    +
    +  def test_newline_smuggler
    +    parser = Puma::HttpParser.new
    +    req = {}
    +    http = "GET / HTTP/1.1\r\nHost: localhost:8080\r\nDummy: x\nDummy2: y\r\n\r\n"
    +
    +    parser.execute(req, http, 0) rescue nil # We test the raise elsewhere.
    +
    +    assert parser.error?, "Parser SHOULD have error"
    +  end
    +
    +  def test_newline_smuggler_two
    +    parser = Puma::HttpParser.new
    +    req = {}
    +    http = "GET / HTTP/1.1\r\nHost: localhost:8080\r\nDummy: x\r\nDummy: y\nDummy2: z\r\n\r\n"
    +
    +    parser.execute(req, http, 0) rescue nil
    +
    +    assert parser.error?, "Parser SHOULD have error"
    +  end
    +
    +  def test_htab_in_header_val
    +    parser = Puma::HttpParser.new
    +    req = {}
    +    http = "GET / HTTP/1.1\r\nHost: localhost:8080\r\nDummy: Valid\tValue\r\n\r\n"
    +
    +    parser.execute(req, http, 0)
    +
    +    assert_equal "Valid\tValue", req['HTTP_DUMMY']
    +  end
     end
    
acdc3ae571df

Merge pull request from GHSA-48w2-rm65-62xx

https://github.com/puma/pumaNate BerkopecOct 12, 2021via ghsa
6 files changed · +95 48
  • ext/puma_http11/http11_parser.c+19 12 modified
    @@ -426,10 +426,13 @@ case 17:
     case 18:
     #line 428 "ext/puma_http11/http11_parser.c"
     	switch( (*p) ) {
    +		case 9: goto tr25;
     		case 13: goto tr26;
     		case 32: goto tr27;
     	}
    -	goto tr25;
    +	if ( 33 <= (*p) && (*p) <= 126 )
    +		goto tr25;
    +	goto st0;
     tr25:
     #line 46 "ext/puma_http11/http11_parser.rl"
     	{ MARK(mark, p); }
    @@ -438,10 +441,14 @@ case 18:
     	if ( ++p == pe )
     		goto _test_eof19;
     case 19:
    -#line 442 "ext/puma_http11/http11_parser.c"
    -	if ( (*p) == 13 )
    -		goto tr29;
    -	goto st19;
    +#line 445 "ext/puma_http11/http11_parser.c"
    +	switch( (*p) ) {
    +		case 9: goto st19;
    +		case 13: goto tr29;
    +	}
    +	if ( 32 <= (*p) && (*p) <= 126 )
    +		goto st19;
    +	goto st0;
     tr9:
     #line 53 "ext/puma_http11/http11_parser.rl"
     	{
    @@ -484,7 +491,7 @@ case 19:
     	if ( ++p == pe )
     		goto _test_eof20;
     case 20:
    -#line 488 "ext/puma_http11/http11_parser.c"
    +#line 495 "ext/puma_http11/http11_parser.c"
     	switch( (*p) ) {
     		case 32: goto tr31;
     		case 60: goto st0;
    @@ -505,7 +512,7 @@ case 20:
     	if ( ++p == pe )
     		goto _test_eof21;
     case 21:
    -#line 509 "ext/puma_http11/http11_parser.c"
    +#line 516 "ext/puma_http11/http11_parser.c"
     	switch( (*p) ) {
     		case 32: goto tr33;
     		case 60: goto st0;
    @@ -526,7 +533,7 @@ case 21:
     	if ( ++p == pe )
     		goto _test_eof22;
     case 22:
    -#line 530 "ext/puma_http11/http11_parser.c"
    +#line 537 "ext/puma_http11/http11_parser.c"
     	switch( (*p) ) {
     		case 43: goto st22;
     		case 58: goto st23;
    @@ -551,7 +558,7 @@ case 22:
     	if ( ++p == pe )
     		goto _test_eof23;
     case 23:
    -#line 555 "ext/puma_http11/http11_parser.c"
    +#line 562 "ext/puma_http11/http11_parser.c"
     	switch( (*p) ) {
     		case 32: goto tr8;
     		case 34: goto st0;
    @@ -571,7 +578,7 @@ case 23:
     	if ( ++p == pe )
     		goto _test_eof24;
     case 24:
    -#line 575 "ext/puma_http11/http11_parser.c"
    +#line 582 "ext/puma_http11/http11_parser.c"
     	switch( (*p) ) {
     		case 32: goto tr37;
     		case 34: goto st0;
    @@ -594,7 +601,7 @@ case 24:
     	if ( ++p == pe )
     		goto _test_eof25;
     case 25:
    -#line 598 "ext/puma_http11/http11_parser.c"
    +#line 605 "ext/puma_http11/http11_parser.c"
     	switch( (*p) ) {
     		case 32: goto tr41;
     		case 34: goto st0;
    @@ -614,7 +621,7 @@ case 25:
     	if ( ++p == pe )
     		goto _test_eof26;
     case 26:
    -#line 618 "ext/puma_http11/http11_parser.c"
    +#line 625 "ext/puma_http11/http11_parser.c"
     	switch( (*p) ) {
     		case 32: goto tr44;
     		case 34: goto st0;
    
  • ext/puma_http11/http11_parser_common.rl+1 1 modified
    @@ -43,7 +43,7 @@
     
       field_name = ( token -- ":" )+ >start_field $snake_upcase_field %write_field;
     
    -  field_value = any* >start_value %write_value;
    +  field_value = ( print | "\t" )* >start_value %write_value;
     
       message_header = field_name ":" " "* field_value :> CRLF;
     
    
  • ext/puma_http11/org/jruby/puma/Http11Parser.java+34 34 modified
    @@ -34,9 +34,9 @@ private static short[] init__puma_parser_key_offsets_0()
     {
     	return new short [] {
     	    0,    0,    8,   17,   27,   29,   30,   31,   32,   33,   34,   36,
    -	   39,   41,   44,   45,   61,   62,   78,   80,   81,   89,   97,  107,
    -	  115,  124,  132,  140,  149,  158,  167,  176,  185,  194,  203,  212,
    -	  221,  230,  239,  248,  257,  266,  275,  284,  293,  302,  303
    +	   39,   41,   44,   45,   61,   62,   78,   83,   87,   95,  103,  113,
    +	  121,  130,  138,  146,  155,  164,  173,  182,  191,  200,  209,  218,
    +	  227,  236,  245,  254,  263,  272,  281,  290,  299,  308,  309
     	};
     }
     
    @@ -52,14 +52,13 @@ private static char[] init__puma_parser_trans_keys_0()
     	   46,   48,   57,   48,   57,   13,   48,   57,   10,   13,   33,  124,
     	  126,   35,   39,   42,   43,   45,   46,   48,   57,   65,   90,   94,
     	  122,   10,   33,   58,  124,  126,   35,   39,   42,   43,   45,   46,
    -	   48,   57,   65,   90,   94,  122,   13,   32,   13,   32,   60,   62,
    -	  127,    0,   31,   34,   35,   32,   60,   62,  127,    0,   31,   34,
    -	   35,   43,   58,   45,   46,   48,   57,   65,   90,   97,  122,   32,
    -	   34,   35,   60,   62,  127,    0,   31,   32,   34,   35,   60,   62,
    -	   63,  127,    0,   31,   32,   34,   35,   60,   62,  127,    0,   31,
    -	   32,   34,   35,   60,   62,  127,    0,   31,   32,   36,   95,   45,
    -	   46,   48,   57,   65,   90,   32,   36,   95,   45,   46,   48,   57,
    -	   65,   90,   32,   36,   95,   45,   46,   48,   57,   65,   90,   32,
    +	   48,   57,   65,   90,   94,  122,    9,   13,   32,   33,  126,    9,
    +	   13,   32,  126,   32,   60,   62,  127,    0,   31,   34,   35,   32,
    +	   60,   62,  127,    0,   31,   34,   35,   43,   58,   45,   46,   48,
    +	   57,   65,   90,   97,  122,   32,   34,   35,   60,   62,  127,    0,
    +	   31,   32,   34,   35,   60,   62,   63,  127,    0,   31,   32,   34,
    +	   35,   60,   62,  127,    0,   31,   32,   34,   35,   60,   62,  127,
    +	    0,   31,   32,   36,   95,   45,   46,   48,   57,   65,   90,   32,
     	   36,   95,   45,   46,   48,   57,   65,   90,   32,   36,   95,   45,
     	   46,   48,   57,   65,   90,   32,   36,   95,   45,   46,   48,   57,
     	   65,   90,   32,   36,   95,   45,   46,   48,   57,   65,   90,   32,
    @@ -71,7 +70,8 @@ private static char[] init__puma_parser_trans_keys_0()
     	   65,   90,   32,   36,   95,   45,   46,   48,   57,   65,   90,   32,
     	   36,   95,   45,   46,   48,   57,   65,   90,   32,   36,   95,   45,
     	   46,   48,   57,   65,   90,   32,   36,   95,   45,   46,   48,   57,
    -	   65,   90,   32,    0
    +	   65,   90,   32,   36,   95,   45,   46,   48,   57,   65,   90,   32,
    +	   36,   95,   45,   46,   48,   57,   65,   90,   32,    0
     	};
     }
     
    @@ -82,7 +82,7 @@ private static byte[] init__puma_parser_single_lengths_0()
     {
     	return new byte [] {
     	    0,    2,    3,    4,    2,    1,    1,    1,    1,    1,    0,    1,
    -	    0,    1,    1,    4,    1,    4,    2,    1,    4,    4,    2,    6,
    +	    0,    1,    1,    4,    1,    4,    3,    2,    4,    4,    2,    6,
     	    7,    6,    6,    3,    3,    3,    3,    3,    3,    3,    3,    3,
     	    3,    3,    3,    3,    3,    3,    3,    3,    3,    1,    0
     	};
    @@ -95,7 +95,7 @@ private static byte[] init__puma_parser_range_lengths_0()
     {
     	return new byte [] {
     	    0,    3,    3,    3,    0,    0,    0,    0,    0,    0,    1,    1,
    -	    1,    1,    0,    6,    0,    6,    0,    0,    2,    2,    4,    1,
    +	    1,    1,    0,    6,    0,    6,    1,    1,    2,    2,    4,    1,
     	    1,    1,    1,    3,    3,    3,    3,    3,    3,    3,    3,    3,
     	    3,    3,    3,    3,    3,    3,    3,    3,    3,    0,    0
     	};
    @@ -108,9 +108,9 @@ private static short[] init__puma_parser_index_offsets_0()
     {
     	return new short [] {
     	    0,    0,    6,   13,   21,   24,   26,   28,   30,   32,   34,   36,
    -	   39,   41,   44,   46,   57,   59,   70,   73,   75,   82,   89,   96,
    -	  104,  113,  121,  129,  136,  143,  150,  157,  164,  171,  178,  185,
    -	  192,  199,  206,  213,  220,  227,  234,  241,  248,  255,  257
    +	   39,   41,   44,   46,   57,   59,   70,   75,   79,   86,   93,  100,
    +	  108,  117,  125,  133,  140,  147,  154,  161,  168,  175,  182,  189,
    +	  196,  203,  210,  217,  224,  231,  238,  245,  252,  259,  261
     	};
     }
     
    @@ -125,23 +125,23 @@ private static byte[] init__puma_parser_indicies_0()
     	   10,    1,   11,    1,   12,    1,   13,    1,   14,    1,   15,    1,
     	   16,   15,    1,   17,    1,   18,   17,    1,   19,    1,   20,   21,
     	   21,   21,   21,   21,   21,   21,   21,   21,    1,   22,    1,   23,
    -	   24,   23,   23,   23,   23,   23,   23,   23,   23,    1,   26,   27,
    -	   25,   29,   28,   30,    1,    1,    1,    1,    1,   31,   32,    1,
    -	    1,    1,    1,    1,   33,   34,   35,   34,   34,   34,   34,    1,
    -	    8,    1,    9,    1,    1,    1,    1,   35,   36,    1,   38,    1,
    -	    1,   39,    1,    1,   37,   40,    1,   42,    1,    1,    1,    1,
    -	   41,   43,    1,   45,    1,    1,    1,    1,   44,    2,   46,   46,
    -	   46,   46,   46,    1,    2,   47,   47,   47,   47,   47,    1,    2,
    -	   48,   48,   48,   48,   48,    1,    2,   49,   49,   49,   49,   49,
    -	    1,    2,   50,   50,   50,   50,   50,    1,    2,   51,   51,   51,
    -	   51,   51,    1,    2,   52,   52,   52,   52,   52,    1,    2,   53,
    -	   53,   53,   53,   53,    1,    2,   54,   54,   54,   54,   54,    1,
    -	    2,   55,   55,   55,   55,   55,    1,    2,   56,   56,   56,   56,
    -	   56,    1,    2,   57,   57,   57,   57,   57,    1,    2,   58,   58,
    -	   58,   58,   58,    1,    2,   59,   59,   59,   59,   59,    1,    2,
    -	   60,   60,   60,   60,   60,    1,    2,   61,   61,   61,   61,   61,
    -	    1,    2,   62,   62,   62,   62,   62,    1,    2,   63,   63,   63,
    -	   63,   63,    1,    2,    1,    1,    0
    +	   24,   23,   23,   23,   23,   23,   23,   23,   23,    1,   25,   26,
    +	   27,   25,    1,   28,   29,   28,    1,   30,    1,    1,    1,    1,
    +	    1,   31,   32,    1,    1,    1,    1,    1,   33,   34,   35,   34,
    +	   34,   34,   34,    1,    8,    1,    9,    1,    1,    1,    1,   35,
    +	   36,    1,   38,    1,    1,   39,    1,    1,   37,   40,    1,   42,
    +	    1,    1,    1,    1,   41,   43,    1,   45,    1,    1,    1,    1,
    +	   44,    2,   46,   46,   46,   46,   46,    1,    2,   47,   47,   47,
    +	   47,   47,    1,    2,   48,   48,   48,   48,   48,    1,    2,   49,
    +	   49,   49,   49,   49,    1,    2,   50,   50,   50,   50,   50,    1,
    +	    2,   51,   51,   51,   51,   51,    1,    2,   52,   52,   52,   52,
    +	   52,    1,    2,   53,   53,   53,   53,   53,    1,    2,   54,   54,
    +	   54,   54,   54,    1,    2,   55,   55,   55,   55,   55,    1,    2,
    +	   56,   56,   56,   56,   56,    1,    2,   57,   57,   57,   57,   57,
    +	    1,    2,   58,   58,   58,   58,   58,    1,    2,   59,   59,   59,
    +	   59,   59,    1,    2,   60,   60,   60,   60,   60,    1,    2,   61,
    +	   61,   61,   61,   61,    1,    2,   62,   62,   62,   62,   62,    1,
    +	    2,   63,   63,   63,   63,   63,    1,    2,    1,    1,    0
     	};
     }
     
    
  • History.md+10 0 modified
    @@ -1,3 +1,8 @@
    +## 5.5.1 / 2021-10-12
    +
    +* Security
    +  * Do not allow LF as a line ending in a header (CVE-2021-41136)
    +
     ## 5.5.0 / 2021-09-19
     
     * Features
    @@ -251,6 +256,11 @@
       * Support parallel tests in verbose progress reporting ([#2223])
       * Refactor error handling in server accept loop ([#2239])
     
    +## 4.3.9 / 2021-10-12
    +
    +* Security
    +  * Do not allow LF as a line ending in a header (CVE-2021-41136)
    +
     ## 4.3.8 / 2021-05-11
     
     * Security
    
  • lib/puma/const.rb+1 1 modified
    @@ -100,7 +100,7 @@ class UnsupportedOption < RuntimeError
       # too taxing on performance.
       module Const
     
    -    PUMA_VERSION = VERSION = "5.5.0".freeze
    +    PUMA_VERSION = VERSION = "5.5.1".freeze
         CODE_NAME = "Zawgyi".freeze
     
         PUMA_SERVER_STRING = ['puma', PUMA_VERSION, CODE_NAME].join(' ').freeze
    
  • test/test_http11.rb+30 0 modified
    @@ -208,4 +208,34 @@ def test_trims_whitespace_from_headers
     
         assert_equal "Strip This", req["HTTP_X_STRIP_ME"]
       end
    +
    +  def test_newline_smuggler
    +    parser = Puma::HttpParser.new
    +    req = {}
    +    http = "GET / HTTP/1.1\r\nHost: localhost:8080\r\nDummy: x\nDummy2: y\r\n\r\n"
    +
    +    parser.execute(req, http, 0) rescue nil # We test the raise elsewhere.
    +
    +    assert parser.error?, "Parser SHOULD have error"
    +  end
    +
    +  def test_newline_smuggler_two
    +    parser = Puma::HttpParser.new
    +    req = {}
    +    http = "GET / HTTP/1.1\r\nHost: localhost:8080\r\nDummy: x\r\nDummy: y\nDummy2: z\r\n\r\n"
    +
    +    parser.execute(req, http, 0) rescue nil
    +
    +    assert parser.error?, "Parser SHOULD have error"
    +  end
    +
    +  def test_htab_in_header_val
    +    parser = Puma::HttpParser.new
    +    req = {}
    +    http = "GET / HTTP/1.1\r\nHost: localhost:8080\r\nDummy: Valid\tValue\r\n\r\n"
    +
    +    parser.execute(req, http, 0)
    +
    +    assert_equal "Valid\tValue", req['HTTP_DUMMY']
    +  end
     end
    
436c71807f00

Fix HTTP request smuggling vulnerability

https://github.com/puma/pumaNate BerkopecOct 10, 2021via ghsa
4 files changed · +84 47
  • ext/puma_http11/http11_parser.c+19 12 modified
    @@ -428,10 +428,13 @@ case 17:
     case 18:
     #line 428 "ext/puma_http11/http11_parser.c"
     	switch( (*p) ) {
    +		case 9: goto tr25;
     		case 13: goto tr26;
     		case 32: goto tr27;
     	}
    -	goto tr25;
    +	if ( 33 <= (*p) && (*p) <= 126 )
    +		goto tr25;
    +	goto st0;
     tr25:
     #line 44 "ext/puma_http11/http11_parser.rl"
     	{ MARK(mark, p); }
    @@ -440,10 +443,14 @@ case 18:
     	if ( ++p == pe )
     		goto _test_eof19;
     case 19:
    -#line 442 "ext/puma_http11/http11_parser.c"
    -	if ( (*p) == 13 )
    -		goto tr29;
    -	goto st19;
    +#line 445 "ext/puma_http11/http11_parser.c"
    +	switch( (*p) ) {
    +		case 9: goto st19;
    +		case 13: goto tr29;
    +	}
    +	if ( 32 <= (*p) && (*p) <= 126 )
    +		goto st19;
    +	goto st0;
     tr9:
     #line 51 "ext/puma_http11/http11_parser.rl"
     	{
    @@ -486,7 +493,7 @@ case 19:
     	if ( ++p == pe )
     		goto _test_eof20;
     case 20:
    -#line 488 "ext/puma_http11/http11_parser.c"
    +#line 495 "ext/puma_http11/http11_parser.c"
     	switch( (*p) ) {
     		case 32: goto tr31;
     		case 60: goto st0;
    @@ -507,7 +514,7 @@ case 20:
     	if ( ++p == pe )
     		goto _test_eof21;
     case 21:
    -#line 509 "ext/puma_http11/http11_parser.c"
    +#line 516 "ext/puma_http11/http11_parser.c"
     	switch( (*p) ) {
     		case 32: goto tr33;
     		case 60: goto st0;
    @@ -528,7 +535,7 @@ case 21:
     	if ( ++p == pe )
     		goto _test_eof22;
     case 22:
    -#line 530 "ext/puma_http11/http11_parser.c"
    +#line 537 "ext/puma_http11/http11_parser.c"
     	switch( (*p) ) {
     		case 43: goto st22;
     		case 58: goto st23;
    @@ -553,7 +560,7 @@ case 22:
     	if ( ++p == pe )
     		goto _test_eof23;
     case 23:
    -#line 555 "ext/puma_http11/http11_parser.c"
    +#line 562 "ext/puma_http11/http11_parser.c"
     	switch( (*p) ) {
     		case 32: goto tr8;
     		case 34: goto st0;
    @@ -573,7 +580,7 @@ case 23:
     	if ( ++p == pe )
     		goto _test_eof24;
     case 24:
    -#line 575 "ext/puma_http11/http11_parser.c"
    +#line 582 "ext/puma_http11/http11_parser.c"
     	switch( (*p) ) {
     		case 32: goto tr37;
     		case 34: goto st0;
    @@ -596,7 +603,7 @@ case 24:
     	if ( ++p == pe )
     		goto _test_eof25;
     case 25:
    -#line 598 "ext/puma_http11/http11_parser.c"
    +#line 605 "ext/puma_http11/http11_parser.c"
     	switch( (*p) ) {
     		case 32: goto tr41;
     		case 34: goto st0;
    @@ -616,7 +623,7 @@ case 25:
     	if ( ++p == pe )
     		goto _test_eof26;
     case 26:
    -#line 618 "ext/puma_http11/http11_parser.c"
    +#line 625 "ext/puma_http11/http11_parser.c"
     	switch( (*p) ) {
     		case 32: goto tr44;
     		case 34: goto st0;
    
  • ext/puma_http11/http11_parser_common.rl+1 1 modified
    @@ -43,7 +43,7 @@
     
       field_name = ( token -- ":" )+ >start_field $snake_upcase_field %write_field;
     
    -  field_value = any* >start_value %write_value;
    +  field_value = ( print | "\t" )* >start_value %write_value;
     
       message_header = field_name ":" " "* field_value :> CRLF;
     
    
  • ext/puma_http11/org/jruby/puma/Http11Parser.java+34 34 modified
    @@ -34,9 +34,9 @@ private static short[] init__puma_parser_key_offsets_0()
     {
     	return new short [] {
     	    0,    0,    8,   17,   27,   29,   30,   31,   32,   33,   34,   36,
    -	   39,   41,   44,   45,   61,   62,   78,   80,   81,   89,   97,  107,
    -	  115,  124,  132,  140,  149,  158,  167,  176,  185,  194,  203,  212,
    -	  221,  230,  239,  248,  257,  266,  275,  284,  293,  302,  303
    +	   39,   41,   44,   45,   61,   62,   78,   83,   87,   95,  103,  113,
    +	  121,  130,  138,  146,  155,  164,  173,  182,  191,  200,  209,  218,
    +	  227,  236,  245,  254,  263,  272,  281,  290,  299,  308,  309
     	};
     }
     
    @@ -52,14 +52,13 @@ private static char[] init__puma_parser_trans_keys_0()
     	   46,   48,   57,   48,   57,   13,   48,   57,   10,   13,   33,  124,
     	  126,   35,   39,   42,   43,   45,   46,   48,   57,   65,   90,   94,
     	  122,   10,   33,   58,  124,  126,   35,   39,   42,   43,   45,   46,
    -	   48,   57,   65,   90,   94,  122,   13,   32,   13,   32,   60,   62,
    -	  127,    0,   31,   34,   35,   32,   60,   62,  127,    0,   31,   34,
    -	   35,   43,   58,   45,   46,   48,   57,   65,   90,   97,  122,   32,
    -	   34,   35,   60,   62,  127,    0,   31,   32,   34,   35,   60,   62,
    -	   63,  127,    0,   31,   32,   34,   35,   60,   62,  127,    0,   31,
    -	   32,   34,   35,   60,   62,  127,    0,   31,   32,   36,   95,   45,
    -	   46,   48,   57,   65,   90,   32,   36,   95,   45,   46,   48,   57,
    -	   65,   90,   32,   36,   95,   45,   46,   48,   57,   65,   90,   32,
    +	   48,   57,   65,   90,   94,  122,    9,   13,   32,   33,  126,    9,
    +	   13,   32,  126,   32,   60,   62,  127,    0,   31,   34,   35,   32,
    +	   60,   62,  127,    0,   31,   34,   35,   43,   58,   45,   46,   48,
    +	   57,   65,   90,   97,  122,   32,   34,   35,   60,   62,  127,    0,
    +	   31,   32,   34,   35,   60,   62,   63,  127,    0,   31,   32,   34,
    +	   35,   60,   62,  127,    0,   31,   32,   34,   35,   60,   62,  127,
    +	    0,   31,   32,   36,   95,   45,   46,   48,   57,   65,   90,   32,
     	   36,   95,   45,   46,   48,   57,   65,   90,   32,   36,   95,   45,
     	   46,   48,   57,   65,   90,   32,   36,   95,   45,   46,   48,   57,
     	   65,   90,   32,   36,   95,   45,   46,   48,   57,   65,   90,   32,
    @@ -71,7 +70,8 @@ private static char[] init__puma_parser_trans_keys_0()
     	   65,   90,   32,   36,   95,   45,   46,   48,   57,   65,   90,   32,
     	   36,   95,   45,   46,   48,   57,   65,   90,   32,   36,   95,   45,
     	   46,   48,   57,   65,   90,   32,   36,   95,   45,   46,   48,   57,
    -	   65,   90,   32,    0
    +	   65,   90,   32,   36,   95,   45,   46,   48,   57,   65,   90,   32,
    +	   36,   95,   45,   46,   48,   57,   65,   90,   32,    0
     	};
     }
     
    @@ -82,7 +82,7 @@ private static byte[] init__puma_parser_single_lengths_0()
     {
     	return new byte [] {
     	    0,    2,    3,    4,    2,    1,    1,    1,    1,    1,    0,    1,
    -	    0,    1,    1,    4,    1,    4,    2,    1,    4,    4,    2,    6,
    +	    0,    1,    1,    4,    1,    4,    3,    2,    4,    4,    2,    6,
     	    7,    6,    6,    3,    3,    3,    3,    3,    3,    3,    3,    3,
     	    3,    3,    3,    3,    3,    3,    3,    3,    3,    1,    0
     	};
    @@ -95,7 +95,7 @@ private static byte[] init__puma_parser_range_lengths_0()
     {
     	return new byte [] {
     	    0,    3,    3,    3,    0,    0,    0,    0,    0,    0,    1,    1,
    -	    1,    1,    0,    6,    0,    6,    0,    0,    2,    2,    4,    1,
    +	    1,    1,    0,    6,    0,    6,    1,    1,    2,    2,    4,    1,
     	    1,    1,    1,    3,    3,    3,    3,    3,    3,    3,    3,    3,
     	    3,    3,    3,    3,    3,    3,    3,    3,    3,    0,    0
     	};
    @@ -108,9 +108,9 @@ private static short[] init__puma_parser_index_offsets_0()
     {
     	return new short [] {
     	    0,    0,    6,   13,   21,   24,   26,   28,   30,   32,   34,   36,
    -	   39,   41,   44,   46,   57,   59,   70,   73,   75,   82,   89,   96,
    -	  104,  113,  121,  129,  136,  143,  150,  157,  164,  171,  178,  185,
    -	  192,  199,  206,  213,  220,  227,  234,  241,  248,  255,  257
    +	   39,   41,   44,   46,   57,   59,   70,   75,   79,   86,   93,  100,
    +	  108,  117,  125,  133,  140,  147,  154,  161,  168,  175,  182,  189,
    +	  196,  203,  210,  217,  224,  231,  238,  245,  252,  259,  261
     	};
     }
     
    @@ -125,23 +125,23 @@ private static byte[] init__puma_parser_indicies_0()
     	   10,    1,   11,    1,   12,    1,   13,    1,   14,    1,   15,    1,
     	   16,   15,    1,   17,    1,   18,   17,    1,   19,    1,   20,   21,
     	   21,   21,   21,   21,   21,   21,   21,   21,    1,   22,    1,   23,
    -	   24,   23,   23,   23,   23,   23,   23,   23,   23,    1,   26,   27,
    -	   25,   29,   28,   30,    1,    1,    1,    1,    1,   31,   32,    1,
    -	    1,    1,    1,    1,   33,   34,   35,   34,   34,   34,   34,    1,
    -	    8,    1,    9,    1,    1,    1,    1,   35,   36,    1,   38,    1,
    -	    1,   39,    1,    1,   37,   40,    1,   42,    1,    1,    1,    1,
    -	   41,   43,    1,   45,    1,    1,    1,    1,   44,    2,   46,   46,
    -	   46,   46,   46,    1,    2,   47,   47,   47,   47,   47,    1,    2,
    -	   48,   48,   48,   48,   48,    1,    2,   49,   49,   49,   49,   49,
    -	    1,    2,   50,   50,   50,   50,   50,    1,    2,   51,   51,   51,
    -	   51,   51,    1,    2,   52,   52,   52,   52,   52,    1,    2,   53,
    -	   53,   53,   53,   53,    1,    2,   54,   54,   54,   54,   54,    1,
    -	    2,   55,   55,   55,   55,   55,    1,    2,   56,   56,   56,   56,
    -	   56,    1,    2,   57,   57,   57,   57,   57,    1,    2,   58,   58,
    -	   58,   58,   58,    1,    2,   59,   59,   59,   59,   59,    1,    2,
    -	   60,   60,   60,   60,   60,    1,    2,   61,   61,   61,   61,   61,
    -	    1,    2,   62,   62,   62,   62,   62,    1,    2,   63,   63,   63,
    -	   63,   63,    1,    2,    1,    1,    0
    +	   24,   23,   23,   23,   23,   23,   23,   23,   23,    1,   25,   26,
    +	   27,   25,    1,   28,   29,   28,    1,   30,    1,    1,    1,    1,
    +	    1,   31,   32,    1,    1,    1,    1,    1,   33,   34,   35,   34,
    +	   34,   34,   34,    1,    8,    1,    9,    1,    1,    1,    1,   35,
    +	   36,    1,   38,    1,    1,   39,    1,    1,   37,   40,    1,   42,
    +	    1,    1,    1,    1,   41,   43,    1,   45,    1,    1,    1,    1,
    +	   44,    2,   46,   46,   46,   46,   46,    1,    2,   47,   47,   47,
    +	   47,   47,    1,    2,   48,   48,   48,   48,   48,    1,    2,   49,
    +	   49,   49,   49,   49,    1,    2,   50,   50,   50,   50,   50,    1,
    +	    2,   51,   51,   51,   51,   51,    1,    2,   52,   52,   52,   52,
    +	   52,    1,    2,   53,   53,   53,   53,   53,    1,    2,   54,   54,
    +	   54,   54,   54,    1,    2,   55,   55,   55,   55,   55,    1,    2,
    +	   56,   56,   56,   56,   56,    1,    2,   57,   57,   57,   57,   57,
    +	    1,    2,   58,   58,   58,   58,   58,    1,    2,   59,   59,   59,
    +	   59,   59,    1,    2,   60,   60,   60,   60,   60,    1,    2,   61,
    +	   61,   61,   61,   61,    1,    2,   62,   62,   62,   62,   62,    1,
    +	    2,   63,   63,   63,   63,   63,    1,    2,    1,    1,    0
     	};
     }
     
    
  • test/test_http11.rb+30 0 modified
    @@ -208,4 +208,34 @@ def test_trims_whitespace_from_headers
     
         assert_equal "Strip This", req["HTTP_X_STRIP_ME"]
       end
    +
    +  def test_newline_smuggler
    +    parser = Puma::HttpParser.new
    +    req = {}
    +    http = "GET / HTTP/1.1\r\nHost: localhost:8080\r\nDummy: x\nDummy2: y\r\n\r\n"
    +
    +    parser.execute(req, http, 0) rescue nil # We test the raise elsewhere.
    +
    +    assert parser.error?, "Parser SHOULD have error"
    +  end
    +
    +  def test_newline_smuggler_two
    +    parser = Puma::HttpParser.new
    +    req = {}
    +    http = "GET / HTTP/1.1\r\nHost: localhost:8080\r\nDummy: x\r\nDummy: y\nDummy2: z\r\n\r\n"
    +
    +    parser.execute(req, http, 0) rescue nil
    +
    +    assert parser.error?, "Parser SHOULD have error"
    +  end
    +
    +  def test_htab_in_header_val
    +    parser = Puma::HttpParser.new
    +    req = {}
    +    http = "GET / HTTP/1.1\r\nHost: localhost:8080\r\nDummy: Valid\tValue\r\n\r\n"
    +
    +    parser.execute(req, http, 0)
    +
    +    assert_equal "Valid\tValue", req['HTTP_DUMMY']
    +  end
     end
    

Vulnerability mechanics

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

References

12

News mentions

0

No linked articles in our index yet.