--- Begin Message ---
Package: release.debian.org
Severity: normal
Tags: trixie
X-Debbugs-Cc: [email protected]
Control: affects -1 + src:apache2
User: [email protected]
Usertags: pu
[ Reason ]
Apache2 is vulnerable to various medium CVEs (CVE-2026-29167, CVE-2026-29170,
CVE-2026-34355, CVE-2026-34356, CVE-2026-42535, CVE-2026-42536,
CVE-2026-43951, CVE-2026-44119, CVE-2026-44185, CVE-2026-44186,
CVE-2026-44631, CVE-2026-48913).
[ Impact ]
Medium security issues
[ Tests ]
Diff contains a test-framework update
[ Risks ]
As usual with Apache, low but not null risk
[ Checklist ]
[X] *all* changes are documented in the d/changelog
[X] I reviewed all changes and I approve them
[X] attach debdiff against the package in (old)stable
[X] the issue is verified as fixed in unstable
[ Changes ]
This release contains only fixes (a lot...)
[ Other info ]
I put here just the debian/ diff. The whole diff is big
diff --git a/debian/changelog b/debian/changelog
index a04158c1..8e4b38fa 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,15 @@
+apache2 (2.4.68-1~deb13u1) trixie; urgency=medium
+
+ * New upstream version (Closes: CVE-2026-29167, CVE-2026-29170,
+ CVE-2026-34355, CVE-2026-34356, CVE-2026-42535, CVE-2026-42536,
+ CVE-2026-43951, CVE-2026-44119, CVE-2026-44185, CVE-2026-44186,
+ CVE-2026-44631, CVE-2026-48913)
+ * Drop CVE-2026-49975_*, now included in upstream
+ * Update debian/convert_docs
+ * Update test framework
+
+ -- Xavier Guimard <[email protected]> Thu, 11 Jun 2026 20:28:43 +0200
+
apache2 (2.4.67-1~deb13u3) trixie-security; urgency=medium
* Fix CVE-2026-49975 (HTTP/2 Bomb)
diff --git a/debian/convert_docs b/debian/convert_docs
index b39a58fa..b8c07370 100755
--- a/debian/convert_docs
+++ b/debian/convert_docs
@@ -49,7 +49,7 @@ foreach my $h (@html) {
elsif ( -f "$SRC/$h.$l" ) {
conv("$SRC/$h.$l", "$tdir$h", $h, $updir);
}
- else {
+ elsif ( ! -e "$tdir$h" ) {
symlink("$updir/en/$h", "$tdir$h");
}
diff --git a/debian/patches/CVE-2026-49975_1.patch
b/debian/patches/CVE-2026-49975_1.patch
deleted file mode 100644
index 28ec9897..00000000
--- a/debian/patches/CVE-2026-49975_1.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From: Stefan Eissing <[email protected]>
-Date: Wed, 27 May 2026 10:50:32 +0200
-Subject: cookie reqest header counting
-
-Account merged cookie headers as an "add" to keep LimitRequestFields effective.
-
-origin: backport,
https://github.com/icing/mod_h2/commit/cb7cd2eec3b6ef02dea62d77de2a38a108af66ee
-bug: https://github.com/icing/mod_h2/pull/324
-bug-security: https://blog.calif.io/p/codex-discovered-a-hidden-http2-bomb
----
- modules/http2/h2_util.c | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/modules/http2/h2_util.c b/modules/http2/h2_util.c
-index b377ff7..b265bc9 100644
---- a/modules/http2/h2_util.c
-+++ b/modules/http2/h2_util.c
-@@ -1719,6 +1719,8 @@ static apr_status_t req_add_header(apr_table_t *headers,
apr_pool_t *pool,
- apr_table_setn(headers, "Cookie",
- apr_psprintf(pool, "%s; %.*s", existing,
- (int)nv->valuelen, nv->value));
-+ /* Treat the merge as an "add" to not escape LimitRequestFields */
-+ *pwas_added = 1;
- return APR_SUCCESS;
- }
- }
diff --git a/debian/patches/CVE-2026-49975_2.patch
b/debian/patches/CVE-2026-49975_2.patch
deleted file mode 100644
index 851e5b36..00000000
--- a/debian/patches/CVE-2026-49975_2.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From: Stefan Eissing <[email protected]>
-Date: Wed, 27 May 2026 11:05:44 +0200
-Subject: ignore duplicate empty cookie headers
-
-origin: backport,
https://github.com/icing/mod_h2/commit/b5c211e7010d31224ac2621664479177314aec96
-bug: https://github.com/icing/mod_h2/pull/324
-bug-security: https://blog.calif.io/p/codex-discovered-a-hidden-http2-bomb
----
- modules/http2/h2_util.c | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/modules/http2/h2_util.c b/modules/http2/h2_util.c
-index b265bc9..b303945 100644
---- a/modules/http2/h2_util.c
-+++ b/modules/http2/h2_util.c
-@@ -1708,6 +1708,8 @@ static apr_status_t req_add_header(apr_table_t *headers,
apr_pool_t *pool,
- && !ap_cstr_casecmpn("cookie", (const char *)nv->name,
nv->namelen)) {
- existing = apr_table_get(headers, "cookie");
- if (existing) {
-+ if (!nv->valuelen)
-+ return APR_SUCCESS;
- /* Cookie header come separately in HTTP/2, but need
- * to be merged by "; " (instead of default ", ")
- */
diff --git a/debian/patches/fhs_compliance.patch
b/debian/patches/fhs_compliance.patch
index ee4715fd..b0c3b185 100644
--- a/debian/patches/fhs_compliance.patch
+++ b/debian/patches/fhs_compliance.patch
@@ -6,7 +6,7 @@ Last-Update: 2026-05-05
--- a/configure
+++ b/configure
-@@ -42443,16 +42443,17 @@
+@@ -42455,16 +42455,17 @@
cat >>confdefs.h <<_ACEOF
#define HTTPD_ROOT "${ap_prefix}"
@@ -28,7 +28,7 @@ Last-Update: 2026-05-05
--- a/configure.in
+++ b/configure.in
-@@ -934,11 +934,11 @@
+@@ -936,11 +936,11 @@
echo $MODLIST | $AWK -f $srcdir/build/build-modules-c.awk > modules.c
APR_EXPAND_VAR(ap_prefix, $prefix)
diff --git a/debian/patches/series b/debian/patches/series
index 2aabdc69..450653aa 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -5,5 +5,3 @@ customize_apxs.patch
build_suexec-custom.patch
reproducible_builds.diff
fix-macro.patch
-CVE-2026-49975_1.patch
-CVE-2026-49975_2.patch
diff --git a/debian/perl-framework/t/apache/expr.t
b/debian/perl-framework/t/apache/expr.t
index 7d62bc04..06e031d0 100644
--- a/debian/perl-framework/t/apache/expr.t
+++ b/debian/perl-framework/t/apache/expr.t
@@ -115,7 +115,6 @@ my @test_cases = (
[ q[toupper(escape('?')) = '%3F' ] => 1 ],
[ q[tolower(toupper(escape('?'))) = '%3f' ] => 1 ],
[ q[%{toupper:%{escape:?}} = '%3F' ] => 1 ],
- [ q[file('] . $file_foo . q[') = 'foo\n' ] => 1 ],
# unary operators
[ q[-n ''] => 0 ],
[ q[-z ''] => 1 ],
@@ -198,11 +197,13 @@ push @test_cases, @bool_test_cases;
push @test_cases, map { ["!($_->[0])" => neg($_->[1]) ] } @bool_test_cases;
if (have_min_apache_version("2.3.13")) {
+ my $restrict2_result = have_min_apache_version('2.4.68') ? undef : 1;
push(@test_cases, (
# functions
- [ q[filesize('] . $file_foo . q[') = 4 ] => 1 ],
- [ q[filesize('] . $file_notexist . q[') = 0 ] => 1 ],
- [ q[filesize('] . $file_zero . q[') = 0 ] => 1 ],
+ [ q[filesize('] . $file_foo . q[') = 4 ] => $restrict2_result ],
+ [ q[filesize('] . $file_notexist . q[') = 0 ] => $restrict2_result ],
+ [ q[filesize('] . $file_zero . q[') = 0 ] => $restrict2_result ],
+ [ q[file('] . $file_foo . q[') = 'foo\n' ] => $restrict2_result ],
# unary operators
[ qq[-d '$file_foo' ] => 0 ],
[ qq[-e '$file_foo' ] => 1 ],
diff --git a/debian/perl-framework/t/apache/pr64339.t
b/debian/perl-framework/t/apache/pr64339.t
index 00097e66..4915418c 100644
--- a/debian/perl-framework/t/apache/pr64339.t
+++ b/debian/perl-framework/t/apache/pr64339.t
@@ -18,7 +18,7 @@ my @testcases = (
['/doc.notxml', "application/notreallyxml", "f\xf3\xf3\n" ],
# Sent with charset=ISO-8859-1 - should be transformed to utf-8
- ['/doc.isohtml', "text/html;charset=utf-8",
"<html><body><p>fóó\n</p></body></html>" ],
+ ['/doc.isohtml', "text/html;charset=utf-8",
"<html><body>.*fóó\n.*</body></html>" ],
);
# mod_xml2enc on trunk behaves quite differently to the 2.4.x version
@@ -42,5 +42,5 @@ foreach my $t (@testcases) {
ok t_cmp($r->code, 200, "fetching ".$t->[0]);
ok t_cmp($r->header('Content-Type'), $t->[1], "content-type header test
for ".$t->[0]);
- ok t_cmp($r->content, $t->[2], "content test for ".$t->[0]);
+ ok t_cmp($r->content, qr/$t->[2]/, "content test for ".$t->[0]);
}
diff --git
a/debian/perl-framework/t/htdocs/modules/include/apexpr/restrict_func.shtml
b/debian/perl-framework/t/htdocs/modules/include/apexpr/restrict_func.shtml
new file mode 100644
index 00000000..31401606
--- /dev/null
+++ b/debian/perl-framework/t/htdocs/modules/include/apexpr/restrict_func.shtml
@@ -0,0 +1,5 @@
+<!--#if expr="file('%{DOCUMENT_ROOT}/foobar.html') =~ /foobar/" -->
+IF_FUNC_TRUE
+<!--#else -->
+IF_FUNC_FALSE
+<!--#endif -->
diff --git a/debian/perl-framework/t/modules/dav.t
b/debian/perl-framework/t/modules/dav.t
index a1b6248b..8ff990d8 100644
--- a/debian/perl-framework/t/modules/dav.t
+++ b/debian/perl-framework/t/modules/dav.t
@@ -10,7 +10,7 @@ use HTTP::Date;
## mod_dav tests
##
-plan tests => 21, [qw(dav HTTP::DAV)];
+plan tests => 22, [qw(dav HTTP::DAV)];
require HTTP::DAV;
my $vars = Apache::Test::vars();
@@ -178,6 +178,15 @@ print "PR 49825: expect 400 bad request got: $actual\n";
ok $actual == 400;
$user_agent->default_header('Content-Range' => undef);
+## Test PUT to .DAV subdirectory (should be blocked in 2.4.68+) ##
+my $dav_uri = "/$dir/.DAV/test.html";
+my $dav_resource = $dav->new_resource( -uri => "http://$server$dav_uri");
+my $expected = have_min_apache_version('2.4.68') ? 403 : 201;
+$response = $dav_resource->put($body);
+$actual = $response->code;
+ok t_cmp($actual, $expected);
+
## clean up ##
+unlink "$htdocs/$dir/.DAV/test.html";
rmdir "$htdocs/$dir/.DAV" or print "warning: could not remove .DAV dir: $!";
rmdir "$htdocs/$dir" or print "warning: could not remove dav dir: $!";
diff --git a/debian/perl-framework/t/modules/headers.t
b/debian/perl-framework/t/modules/headers.t
index 4892b95c..40bd5c32 100644
--- a/debian/perl-framework/t/modules/headers.t
+++ b/debian/perl-framework/t/modules/headers.t
@@ -115,7 +115,27 @@ my @testcases = (
[ ],
[ 'Test-Header' => 'foo' ],
],
+ # 500 error test - invalid regex pattern
+ [
+ "Header edit Test-Header (unclosed bar", #
malformed regex (unmatched parenthesis)
+ [ ],
+ [ ],
+ 500,
+ ],
);
+if (have_min_apache_version('2.4.68')) {
+ push(@testcases,
+ (
+ # edit*
+ [
+ "Header set Test-Header \"expr=%{base64:%{file:$htaccess}}\"", # no
file() in htaccess
+ [ ],
+ [ ],
+ 500,
+ ],
+ )
+ );
+}
if (have_min_apache_version('2.5.1')) {
push(@testcases,
(
@@ -297,6 +317,9 @@ sub test_header2 {
my @test = @_;
my $h = HTTP::Headers->new;
+ # Extract expected status code (default to 200 if not specified)
+ my $expected_status = $test[0][3] // 200;
+
print "\n\n\n";
for (my $i = 0; $i < scalar @{$test[0][1]}; $i += 2) {
print "Header sent n°" . $i/2 . ":\n";
@@ -312,22 +335,30 @@ sub test_header2 {
##
my $r = HTTP::Request->new('GET',
"http://$hostport/modules/headers/htaccess/", $h);
my $res = $ua->request($r);
- ok t_cmp($res->code, 200, "Checking return code is '200'");
+ ok t_cmp($res->code, $expected_status, "Checking return code is
'$expected_status'");
- my $isok = 1;
- for (my $i = 0; $i < scalar @{$test[0][2]}; $i += 2) {
- print "\n";
- print "Header received n°" . $i/2 . ":\n";
- print " header: " . $test[0][2][$i] . "\n";
- print " expected: " . $test[0][2][$i+1] . "\n";
- if ($res->header($test[0][2][$i])) {
- print " received: " . $res->header($test[0][2][$i]) . "\n";
- } else {
- print " received: <undefined>\n";
+ # Only validate headers if we expect a successful response
+ if ($expected_status == 200) {
+ my $isok = 1;
+ for (my $i = 0; $i < scalar @{$test[0][2]}; $i += 2) {
+ print "\n";
+ print "Header received n°" . $i/2 . ":\n";
+ print " header: " . $test[0][2][$i] . "\n";
+ print " expected: " . $test[0][2][$i+1] . "\n";
+ if ($res->header($test[0][2][$i])) {
+ print " received: " . $res->header($test[0][2][$i]) . "\n";
+ } else {
+ print " received: <undefined>\n";
+ }
+ $isok = $isok && $res->header($test[0][2][$i]) &&
$test[0][2][$i+1] eq $res->header($test[0][2][$i]);
}
- $isok = $isok && $res->header($test[0][2][$i]) && $test[0][2][$i+1] eq
$res->header($test[0][2][$i]);
- }
- print "\nResponse received is:\n" . $res->as_string;
+ print "\nResponse received is:\n" . $res->as_string;
- ok $isok;
+ ok $isok;
+ } else {
+ # For error responses, skip header validation
+ print "\nExpected error response received (status $expected_status)\n";
+ print "Response received is:\n" . $res->as_string;
+ ok 1;
+ }
}
diff --git a/debian/perl-framework/t/modules/include.t
b/debian/perl-framework/t/modules/include.t
index 99644971..a4b1e80b 100644
--- a/debian/perl-framework/t/modules/include.t
+++ b/debian/perl-framework/t/modules/include.t
@@ -85,7 +85,7 @@ my %test = (
"echo3.shtml" => ['<!--#echo var="DOCUMENT_NAME" -->',
"retagged1"],
"notreal.shtml" => "pass <!--",
"malformed.shtml" => "[an error occurred while processing this ".
- "directive] malformed.shtml",
+ "directive]",
"exec/off/cmd.shtml" => "[an error occurred while processing this ".
"directive]",
"exec/on/cmd.shtml" => "pass",
@@ -107,9 +107,11 @@ my %test = (
my %ap_expr_test = (
"apexpr/if1.shtml" => "pass",
"apexpr/err.shtml" => "[an error occurred while processing this ".
- "directive] err.shtml",
+ "directive]",
"apexpr/restrict.shtml" => "[an error occurred while processing this ".
- "directive] restrict.shtml",
+ "directive]",
+"apexpr/restrict_func.shtml" => "[an error occurred while processing this ".
+ "directive]",
"apexpr/var.shtml" => "pass pass pass",
"apexpr/lazyvar.shtml" => "pass",
);
@@ -303,6 +305,12 @@ foreach $doc (sort keys %tests) {
skip "Skipping 'exec cgi' test; no cgi module.", 2;
}
}
+ elsif ($doc =~ m/malformed|apexpr/) {
+ ok t_cmp(super_chomp(GET_BODY "$dir$doc"),
+ qr/\Q$tests{$doc}\E/,
+ "GET $dir$doc"
+ );
+ }
else {
ok t_cmp(super_chomp(GET_BODY "$dir$doc"),
$tests{$doc},
diff --git a/debian/perl-framework/t/modules/proxy_fcgi.t
b/debian/perl-framework/t/modules/proxy_fcgi.t
index dce4a804..6da6253f 100644
--- a/debian/perl-framework/t/modules/proxy_fcgi.t
+++ b/debian/perl-framework/t/modules/proxy_fcgi.t
@@ -154,7 +154,7 @@ sub run_fcgi_envvar_request
}
if(defined($fcgi_port)) {
- if ($r->code ge '500') {
+ if ($r->code ge '400') {
# Unknown failure, probably the request didn't hit the FCGI child
# process, so it will hang waiting for our request
kill 'TERM', $child;
@@ -328,6 +328,11 @@ foreach my $url (@udstests) {
}
for my $t (@balancertests) {
+ if (!have_module("proxy_balancer")) {
+ skip "no proxy_balancer";
+ skip "no proxy_balancer";
+ next;
+ }
my $url = $t->{"url"};
my $pathinfo = $t->{"pathinfo"};
$envs = run_fcgi_envvar_request($fcgi_port, $url);
diff --git a/debian/perl-framework/t/modules/setenvif.t
b/debian/perl-framework/t/modules/setenvif.t
index cb561c28..0b13fb81 100644
--- a/debian/perl-framework/t/modules/setenvif.t
+++ b/debian/perl-framework/t/modules/setenvif.t
@@ -56,7 +56,7 @@ my @var = qw(VAR_ONE VAR_TWO VAR_THREE);
my $htaccess = "$htdocs/modules/setenvif/htaccess/.htaccess";
-plan tests => @var * 10 + (keys %var_att) * 6 * @var + 4,
+plan tests => @var * 10 + (keys %var_att) * 6 * @var + 5,
have_module qw(setenvif include);
sub write_htaccess {
@@ -178,6 +178,16 @@ else {
skip "skipping inverted match test with version <2.4.38"
}
+if (need_min_apache_version("2.4.67")) {
+ # file() access should be disallowed in htaccess context
+ write_htaccess("SetEnvIfExpr \"file('$htdocs/foobar.html') =~ /(.+)/\"
VAR_ONE=\$0");
+ $body = GET_BODY $page;
+ ok ! t_cmp($body, qr/^1:foobar/);
+}
+else {
+ skip "skipping test for CVE-2026-24072 in version <2.4.67";
+}
+
## i think this should work, but it doesnt.
## leaving it commented now pending investigation.
## seems you cant override variables that have been previously set.
--- End Message ---