Package: release.debian.org
Severity: normal
Tags: trixie
X-Debbugs-Cc: [email protected]
Control: affects -1 + src:starlet
User: [email protected]
Usertags: pu

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

In coordination with the security team, I've uploaded 
starlet/0.31-2+deb13u1 to trixie in order to fix 
https://security-tracker.debian.org/tracker/CVE-2026-40561
aka #1135584

| Starlet versions through 0.31 for Perl allows HTTP Request Smuggling 
| via Improper Header Precedence. Starlet incorrectly prioritizes 
| "Content-Length" over "Transfer-Encoding: chunked" when both headers 
| are present in an HTTP request. …

The fix is in a quilt patch, which is taken from an upstream commit, 
and is already uploaded to unstable.

The commit contains two tests, the actual code changes are small and 
well-documented.

Find attached the complete debdiff against the version in trixie.


Thanks in advance,
gregor

-----BEGIN PGP SIGNATURE-----

iQKTBAEBCgB9FiEE0eExbpOnYKgQTYX6uzpoAYZJqgYFAmn7epNfFIAAAAAALgAo
aXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldEQx
RTEzMTZFOTNBNzYwQTgxMDREODVGQUJCM0E2ODAxODY0OUFBMDYACgkQuzpoAYZJ
qgYYeA/8DP50vKs0vG0vnFkWHNl7MquOyYLiAWgFmQ6IPFsEM2hF63/xCcvmFR/Q
mTrQb9XwL+8Vyavlmh8W7zZp3uZMWmwiNFpPEXTQpZCJOUDdqWW0oH5vBPJEPCpg
LHZSCg2K+TruyfKAWgJCwxXY1vGGiLyokLCO6lBZXNE20dpTJVvZTCPMCk61rW7R
ZzBADwwYe3HhTyt9EDgIOM+2k8IFtuVIpvUH4EiRZCLAf2g1gbnnPoNH2I2kMtzN
otlcXBiZVVjr1CBHdsyxeApiKnb1WE6q9/KOlG96LR0tSFV0XWHYEnhpgUAYQW1t
tF5h2EHv5jWOtmaur8VefS0VIhJT6c1tVH80+doUKG6kUr5BtyT4WUp97HdnTsW3
dQOgJ72wnkO9jOED5MH/jeE/IFr7QHosE6ebofvw+3C+8aG4WcogEFT1k5PiBtR6
kDYeb9NI/o0IKFGF+z5y49gNekJDmswrQVH2eae3BH0KN9T9mTN8Mh7p6LZQm2jm
EqQfC/swb3GC5KXmBU+kVhUOvs1YELSM4PNmia+ms1WsXxY5htlpq+0LL1INUIBp
kq875OJ30GzS0A6nyHkM/LCaFYxGI/3rnXyCROmch61I/u1gsBDjpjlZnEzO7QTB
OMuuoyHdH38pl3++WqZKFks96aXL7W4f7xtDducnjtfqlHsCaTA=
=iCfQ
-----END PGP SIGNATURE-----
diff -Nru starlet-0.31/debian/changelog starlet-0.31/debian/changelog
--- starlet-0.31/debian/changelog       2022-06-29 00:47:29.000000000 +0200
+++ starlet-0.31/debian/changelog       2026-05-06 17:21:29.000000000 +0200
@@ -1,3 +1,10 @@
+starlet (0.31-2+deb13u1) trixie; urgency=medium
+
+  * Add patch from upstream Git to prevent HTTP Smuggling.
+    Fixes CVE-2026-40561. (Closes: #1135584)
+
+ -- gregor herrmann <[email protected]>  Wed, 06 May 2026 17:21:29 +0200
+
 starlet (0.31-2) unstable; urgency=medium
 
   [ Salvatore Bonaccorso ]
diff -Nru starlet-0.31/debian/patches/0001-Prevent-HTTP-Smuggling.patch 
starlet-0.31/debian/patches/0001-Prevent-HTTP-Smuggling.patch
--- starlet-0.31/debian/patches/0001-Prevent-HTTP-Smuggling.patch       
1970-01-01 01:00:00.000000000 +0100
+++ starlet-0.31/debian/patches/0001-Prevent-HTTP-Smuggling.patch       
2026-05-06 17:21:29.000000000 +0200
@@ -0,0 +1,185 @@
+From a7d5dfd1862aafa43e5eaca0fdb6acf4cc15b2d0 Mon Sep 17 00:00:00 2001
+From: Tokuhiro Matsuno <[email protected]>
+Date: Tue, 19 Nov 2019 19:19:17 +0900
+Subject: [PATCH] Prevent HTTP Smuggling.
+
+- Deny request contains both `transfer-encoding` and `content-length`
+  headers.
+- Deny request contains non-digits in `content-length` header.
+
+
+Bugs-Debian: https://bugs.debian.org/1135584
+Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2026-40561
+
+---
+ lib/Starlet/Server.pm                         | 15 +++++
+ ...ing-content-length-and-transfer-encoding.t | 59 +++++++++++++++++++
+ ...smuggling-multiple-content-length-header.t | 57 ++++++++++++++++++
+ 3 files changed, 131 insertions(+)
+ create mode 100644 t/15smuggling-content-length-and-transfer-encoding.t
+ create mode 100644 t/16smuggling-multiple-content-length-header.t
+
+diff --git a/lib/Starlet/Server.pm b/lib/Starlet/Server.pm
+index 0513a42..d68d02a 100644
+--- a/lib/Starlet/Server.pm
++++ b/lib/Starlet/Server.pm
+@@ -296,6 +296,17 @@ sub handle_connection {
+             $buf = substr $buf, $reqlen;
+             my $chunked = do { no warnings; lc delete 
$env->{HTTP_TRANSFER_ENCODING} eq 'chunked' };
+ 
++            # If a message is received with both a Transfer-Encoding and a
++            # Content-Length header field, the Transfer-Encoding overrides the
++            # Content-Length.  Such a message might indicate an attempt to
++            # perform request smuggling (Section 9.5) or response splitting
++            # (Section 9.4) and ought to be handled as an error.  A sender 
MUST
++            # remove the received Content-Length field prior to forwarding 
such
++            # a message downstream.
++            if ($chunked && $env->{CONTENT_LENGTH}) {
++                last; # Return bad response.
++            }
++
+             if ( $env->{HTTP_EXPECT} ) {
+                 if ( lc $env->{HTTP_EXPECT} eq '100-continue' ) {
+                     $self->write_all($conn, "HTTP/1.1 100 
Continue\015\012\015\012")
+@@ -307,6 +318,10 @@ sub handle_connection {
+             }
+ 
+             if (my $cl = $env->{CONTENT_LENGTH}) {
++                if ($cl !~ /^[0-9]+$/) { # content-length header must be 
digits.
++                    last; # Return bad response
++                }
++
+                 my $buffer = Plack::TempBuffer->new($cl);
+                 while ($cl > 0) {
+                     my $chunk;
+diff --git a/t/15smuggling-content-length-and-transfer-encoding.t 
b/t/15smuggling-content-length-and-transfer-encoding.t
+new file mode 100644
+index 0000000..c6a0645
+--- /dev/null
++++ b/t/15smuggling-content-length-and-transfer-encoding.t
+@@ -0,0 +1,59 @@
++use strict;
++use Test::TCP;
++use Plack::Test;
++use HTTP::Request;
++use HTTP::Message::PSGI;
++use Test::More;
++use Digest::MD5;
++use Plack::Test::Server;
++use Test::TCP;
++use IO::Socket::INET;
++
++$ENV{PLACK_SERVER} = 'Starlet';
++
++my $app = sub {
++    my $env = shift;
++    my $body;
++    my $clen = $env->{CONTENT_LENGTH};
++    while ($clen > 0) {
++        $env->{'psgi.input'}->read(my $buf, $clen) or last;
++        $clen -= length $buf;
++        $body .= $buf;
++    }
++    return [ 200, [ 'Content-Type', 'text/plain', 'X-Content-Length', 
$env->{CONTENT_LENGTH} ], [ $body ] ];
++};
++
++my $server = Test::TCP->new(
++    code => sub {
++        my $sock_or_port = shift;
++        my $server = Plack::Loader->auto(
++            port => $sock_or_port,
++            host => '127.0.0.1'
++        );
++        $server->run($app);
++        exit;
++    },
++);
++
++my $sock = IO::Socket::INET->new(
++    PeerAddr => '127.0.0.1',
++    PeerPort => $server->port,
++    Proto => 'tcp',
++);
++
++print {$sock} (
++    "GET / HTTP/1.1\015\012"
++    . "content-length: 3\015\012"
++    . "Transfer-Encoding: chunked\015\012"
++    . "connection: close\015\012"
++    . "\015\012"
++    . "8\015\012"
++    . "SMUGGLED\015\012"
++    . "0\015\012"
++);
++
++my $res_str = do { local $/; <$sock> };
++my ($status_line, ) = split /\015\012/, $res_str;
++is $status_line, 'HTTP/1.1 400 Bad Request';
++
++done_testing;
+diff --git a/t/16smuggling-multiple-content-length-header.t 
b/t/16smuggling-multiple-content-length-header.t
+new file mode 100644
+index 0000000..55e69db
+--- /dev/null
++++ b/t/16smuggling-multiple-content-length-header.t
+@@ -0,0 +1,57 @@
++use strict;
++use Test::TCP;
++use Plack::Test;
++use HTTP::Request;
++use HTTP::Message::PSGI;
++use Test::More;
++use Digest::MD5;
++use Plack::Test::Server;
++use Test::TCP;
++use IO::Socket::INET;
++
++$ENV{PLACK_SERVER} = 'Starlet';
++
++my $app = sub {
++    my $env = shift;
++    my $body;
++    my $clen = $env->{CONTENT_LENGTH};
++    while ($clen > 0) {
++        $env->{'psgi.input'}->read(my $buf, $clen) or last;
++        $clen -= length $buf;
++        $body .= $buf;
++    }
++    return [ 200, [ 'Content-Type', 'text/plain', 'X-Content-Length', 
$env->{CONTENT_LENGTH} ], [ $body ] ];
++};
++
++my $server = Test::TCP->new(
++    code => sub {
++        my $sock_or_port = shift;
++        my $server = Plack::Loader->auto(
++            port => $sock_or_port,
++            host => '127.0.0.1'
++        );
++        $server->run($app);
++        exit;
++    },
++);
++
++my $sock = IO::Socket::INET->new(
++    PeerAddr => '127.0.0.1',
++    PeerPort => $server->port,
++    Proto => 'tcp',
++);
++
++print {$sock} (
++    "GET / HTTP/1.1\015\012"
++    . "content-length: 3\015\012"
++    . "content-length: 9\015\012"
++    . "connection: close\015\012"
++    . "\015\012"
++    . "123456789"
++);
++
++my $res_str = do { local $/; <$sock> };
++my ($status_line, ) = split /\015\012/, $res_str;
++is $status_line, 'HTTP/1.1 400 Bad Request';
++
++done_testing;
+-- 
+2.53.0
+
diff -Nru starlet-0.31/debian/patches/series starlet-0.31/debian/patches/series
--- starlet-0.31/debian/patches/series  2022-06-29 00:47:29.000000000 +0200
+++ starlet-0.31/debian/patches/series  2026-05-06 17:21:29.000000000 +0200
@@ -1 +1,2 @@
 calculate-baybridge.jpg.patch
+0001-Prevent-HTTP-Smuggling.patch

Reply via email to