1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
|
From: Mohammad Sajid Anwar <mohammad.anwar@yahoo.com>
Date: Thu, 28 Aug 2025 20:12:23 +0100
Subject: - Sanitize all user-supplied values before inserting into HTTP
headers. Thanks Maxim Kosenko for raising the issue with recommended
solution. Thanks breno for the patch. Thanks Stig Palmquist for assiginig
it CVE-2025-40927.
Origin: https://github.com/manwar/CGI--Simple/commit/0c1a2e0b8f24804d33daac686666ac944363a630
Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2025-40927
---
Changes | 6 ++++++
lib/CGI/Simple.pm | 12 +++++++-----
lib/CGI/Simple/Cookie.pm | 2 +-
lib/CGI/Simple/Standard.pm | 2 +-
lib/CGI/Simple/Util.pm | 2 +-
t/120.header-crlf.t | 28 ++++++++++++++++++++--------
6 files changed, 36 insertions(+), 16 deletions(-)
diff --git a/lib/CGI/Simple.pm b/lib/CGI/Simple.pm
index ebf13706f987..5125533dfdb1 100644
--- a/lib/CGI/Simple.pm
+++ b/lib/CGI/Simple.pm
@@ -998,6 +998,7 @@ sub header {
);
my $CRLF = $self->crlf;
+ my $ALL_POSSIBLE_CRLF = qr/(?:\r\n|\n|\015\012)/;
# CR escaping for values, per RFC 822
for my $header (
@@ -1007,11 +1008,12 @@ sub header {
if ( defined $header ) {
# From RFC 822:
# Unfolding is accomplished by regarding CRLF immediately
- # followed by a LWSP-char as equivalent to the LWSP-char.
- $header =~ s/$CRLF(\s)/$1/g;
+ # followed by a LWSP-char as equivalent to the LWSP-char
+ # (defined in the RFC as a space or a horizontal tab).
+ $header =~ s/$ALL_POSSIBLE_CRLF([ \t])/$1/g;
# All other uses of newlines are invalid input.
- if ( $header =~ m/$CRLF/ ) {
+ if ( $header =~ m/$ALL_POSSIBLE_CRLF/ ) {
# shorten very long values in the diagnostic
$header = substr( $header, 0, 72 ) . '...'
if ( length $header > 72 );
diff --git a/t/120.header-crlf.t b/t/120.header-crlf.t
index d6a4dca78c41..7834b77e8022 100644
--- a/t/120.header-crlf.t
+++ b/t/120.header-crlf.t
@@ -1,5 +1,5 @@
use strict;
-use Test::More tests => 2;
+use Test::More tests => 9;
use Test::Exception;
use CGI::Simple;
@@ -7,14 +7,26 @@ my $cgi = CGI::Simple->new;
my $CRLF = $cgi->crlf;
-is( $cgi->header( '-Test' => "test$CRLF part" ),
- "Test: test part"
+my %possible_crlf = (
+ '\n' => "\n",
+ '\r\n' => "\r\n",
+ '\015\012' => "\015\012",
+);
+for my $k (sort keys %possible_crlf) {
+ is(
+ $cgi->header( '-Test' => "test$possible_crlf{$k} part" ),
+ "Test: test part"
. $CRLF
. 'Content-Type: text/html; charset=ISO-8859-1'
. $CRLF
- . $CRLF
-);
+ . $CRLF,
+ "header value with $k + space drops the $k and is valid"
+ );
-throws_ok { $cgi->header( '-Test' => "test$CRLF$CRLF part" ) }
-qr/Invalid header value contains a newline not followed by whitespace: test="test/,
- 'invalid CRLF caught';
+ throws_ok { $cgi->header( '-Test' => "test$possible_crlf{$k}$possible_crlf{$k} part" ) }
+ qr/Invalid header value contains a newline not followed by whitespace: test="test/,
+ 'invalid CRLF caught for double ' . $k;
+ throws_ok { $cgi->header( '-Test' => "test$possible_crlf{$k}part" ) }
+ qr/Invalid header value contains a newline not followed by whitespace: test="test/,
+ "invalid $k caught not followed by whitespace";
+}
--
2.51.0
|