Version in base suite: 1.6.5+dfsg-1+deb12u8 Base version: roundcube_1.6.5+dfsg-1+deb12u8 Target version: roundcube_1.6.5+dfsg-1+deb12u9 Base file: /srv/ftp-master.debian.org/ftp/pool/main/r/roundcube/roundcube_1.6.5+dfsg-1+deb12u8.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/r/roundcube/roundcube_1.6.5+dfsg-1+deb12u9.dsc changelog | 24 patches/Avoid-dependency-on-new-package-mlocati-ip-lib.patch | 275 +++++++++-- patches/CVE-2026-48842.patch | 55 ++ patches/CVE-2026-48843.patch | 86 +++ patches/CVE-2026-48844.patch | 73 ++ patches/CVE-2026-48845.patch | 39 + patches/CVE-2026-48846.patch | 91 +++ patches/CVE-2026-48847.patch | 80 +++ patches/CVE-2026-48848.patch | 63 ++ patches/CVE-2026-48849.patch | 26 + patches/series | 10 11 files changed, 791 insertions(+), 31 deletions(-) dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmpu2h6_5ms/roundcube_1.6.5+dfsg-1+deb12u8.dsc: no acceptable signature found dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmpu2h6_5ms/roundcube_1.6.5+dfsg-1+deb12u9.dsc: no acceptable signature found diff -Nru roundcube-1.6.5+dfsg/debian/changelog roundcube-1.6.5+dfsg/debian/changelog --- roundcube-1.6.5+dfsg/debian/changelog 2026-03-20 18:15:19.000000000 +0000 +++ roundcube-1.6.5+dfsg/debian/changelog 2026-05-25 23:08:43.000000000 +0000 @@ -1,3 +1,27 @@ +roundcube (1.6.5+dfsg-1+deb12u9) bookworm-security; urgency=high + + * Cherry pick upstream security fixes from v1.6.16 (closes: #1137507). + + Fix CVE-2026-48842: pre-auth SQL injection in `virtuser_query` plugin + via `preg_replace()` backslash escape bypass. + + Fix CVE-2026-48843: SSRF bypass via specific local address URLs. Add + support non quad-dotted IPs and non-decimal fields to + d/p/Avoid-dependency-on-new-package-mlocati-ip-lib.patch in order to + match the new upstream behavior. + + Fix CVE-2026-48844: Code injection vulnerability via code evaluation + support in LDAP autovalues option. Code evaluation support has now been + removed. + + Fix CVE-2026-48845: Local/private URL fetch bypass when remote resources + were not allowed. + + Fix CVE-2026-48846: Bypass of remote image blocking via CSS `var()`. + + Fix CVE-2026-48847: Pre-auth arbitrary file delete via redis/memcache + session poisoning bypass. + + Fix CVE-2026-48848: CSS injection bypass in HTML sanitizer via SVG + . + + Fix CVE-2026-48849: Stored XSS/HTML/CSS injection in subject field of + the draft restore dialog. + + -- Guilhem Moulin Tue, 26 May 2026 01:08:43 +0200 + roundcube (1.6.5+dfsg-1+deb12u8) bookworm-security; urgency=high * Cherry pick upstream security fixes from v1.6.14 and v1.6.15 (closes: diff -Nru roundcube-1.6.5+dfsg/debian/patches/Avoid-dependency-on-new-package-mlocati-ip-lib.patch roundcube-1.6.5+dfsg/debian/patches/Avoid-dependency-on-new-package-mlocati-ip-lib.patch --- roundcube-1.6.5+dfsg/debian/patches/Avoid-dependency-on-new-package-mlocati-ip-lib.patch 2026-03-20 18:15:19.000000000 +0000 +++ roundcube-1.6.5+dfsg/debian/patches/Avoid-dependency-on-new-package-mlocati-ip-lib.patch 2026-05-25 23:08:43.000000000 +0000 @@ -4,46 +4,176 @@ Which as of today is not present in Debian. The dependency was introduced in 27ec6cc9cb25e1ef8b4d4ef39ce76d619caa6870 in order to fix a -CVE-2026-35540. While it can be uploaded to sid, we need another -solution to fix the vulnerability for older suites. +CVE-2026-35540 and its follow-up CVE-2026-48843. While it can be +uploaded to sid, we need another solution to fix the vulnerability for +older suites. Bug-Debian: https://bugs.debian.org/1131182 Forwarded: not-needed --- - program/lib/Roundcube/rcube_utils.php | 45 ++++++++++++++++++++++++----------- - tests/Framework/Utils.php | 6 +++++ - 2 files changed, 37 insertions(+), 14 deletions(-) + program/lib/Roundcube/rcube_utils.php | 160 +++++++++++++++++++++++++++++----- + tests/Framework/Utils.php | 85 ++++++++++++++++++ + 2 files changed, 223 insertions(+), 22 deletions(-) diff --git a/program/lib/Roundcube/rcube_utils.php b/program/lib/Roundcube/rcube_utils.php -index 8ff1db8..c5532be 100644 +index 0ddd910..43be2af 100644 --- a/program/lib/Roundcube/rcube_utils.php +++ b/program/lib/Roundcube/rcube_utils.php -@@ -1,7 +1,5 @@ +@@ -1,8 +1,5 @@ $field) { ++ /* process each field except the last one; values must not exceed 0xFF */ ++ if (preg_match('/^0[xX]0*([0-9A-Fa-f]{0,2})$/D', $field, $matches)) { ++ /* hexadecimal field, 0x00 to 0xFF */ ++ $b = $matches[1] === '' ? 0 : hexdec($matches[1]); ++ } elseif (preg_match('/^0+([1-3][0-7][0-7]|[1-7][0-7]?|)$/D', $field, $matches)) { ++ /* octal field, o0 to o377 */ ++ $b = $matches[1] === '' ? 0 : intval($matches[1], 8); ++ } elseif (preg_match('/^(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]?)$/D', $field)) { ++ /* decimal field, 1 to 255 */ ++ $b = intval($field, 10); + } else { -+ $address = @inet_pton($address); ++ /* invalid field */ ++ return false; + } ++ $address[$i] = chr($b); ++ } + -+ if (is_string($address)) { - $nets = [ ++ /* split into 2 groups of 16 bits to avoid overflowing PHP_INT_MAX on 32-bits platforms */ ++ $hi = $li = 0x0000; ++ $carry = null; ++ if (preg_match('/^0[xX]0*([0-9A-Fa-f]{0,8})$/D', $field_last, $matches)) { ++ /* hexadecimal field, 0x00 to 0xFFFFFFFF */ ++ if (strlen($matches[1]) > 4) { ++ $hi = hexdec(substr($matches[1], 0, -4)); ++ $li = hexdec(substr($matches[1], -4)); ++ } elseif ($matches[1] !== '') { ++ $li = hexdec($matches[1]); ++ } ++ } elseif (preg_match('/^0+([1-3][0-7]{10}|[1-7][0-7]{0,9}|)$/D', ++ $field_last, $matches)) { ++ /* octal field, o0 to o37777777777 */ ++ if ($matches[1] !== '') { ++ $base = 8; ++ $hi = intval(substr($matches[1], 0, 10), $base); ++ $li = $hi % (1 << 16); ++ $hi = intdiv($hi, 1 << 16); /* <= 65535 */ ++ if (strlen($matches[1]) > 10) { ++ $carry = substr($matches[1], -1); /* last digit */ ++ } ++ } ++ } elseif (preg_match('/^[1-9][0-9]{0,9}$/D', $field_last)) { ++ /* decimal field, 1 to 9999999999 (values >=2^32 are rejected later) */ ++ $base = 10; ++ $hi = intval(substr($field_last, 0, 9), $base); ++ $li = $hi % (1 << 16); ++ $hi = intdiv($hi, 1 << 16); /* <= 152587 */ ++ if (strlen($field_last) > 9) { ++ $carry = substr($field_last, -1); /* last digit */ ++ } ++ } else { ++ /* invalid field */ ++ return false; ++ } ++ if ($carry !== null) { ++ /* carry over the last digit; there won't be any overflow ++ * since the value won't exceed 152587 * $base + $base-1 */ ++ $li = $li * $base + intval($carry, $base); ++ $hi = $hi * $base + intdiv($li, 1 << 16); ++ $li %= 1 << 16; ++ } ++ ++ $i = count($fields); ++ if ($hi === 0x0000 && $li <= 0x00ff && $i <= 3) { ++ /* first 0-3 bytes have been set already, now set the last byte */ ++ $address[3] = chr($li); ++ } elseif ($hi === 0x0000 && $li <= 0xffff && $i <= 2) { ++ /* first 0-2 bytes have been set already, now set the last 2 bytes */ ++ $address[2] = chr( intdiv($li, 1 << 8) ); ++ $address[3] = chr( $li % (1 << 8) ); ++ } elseif ($hi <= 0x00ff && $li <= 0xffff && $i <= 1) { ++ /* first 0-1 bytes have been set already, now set the last 3 bytes */ ++ $address[1] = chr( $hi ); ++ $address[2] = chr( intdiv($li, 1 << 8) ); ++ $address[3] = chr( $li % (1 << 8) ); ++ } elseif ($hi <= 0xffff && $li <= 0xffff && $i === 0) { ++ /* set all 4 bytes */ ++ $address[0] = chr( intdiv($hi, 1 << 8) ); ++ $address[1] = chr( $hi % (1 << 8) ); ++ $address[2] = chr( intdiv($li, 1 << 8) ); ++ $address[3] = chr( $li % (1 << 8) ); ++ } else { ++ /* overflow, all numeric values must be <2^32 */ ++ return false; ++ } ++ return $address; ++ } ++ + /** + * Check if an URL point to a local network location. + * +@@ -434,37 +541,46 @@ class rcube_utils + $host = parse_url($url, \PHP_URL_HOST); + + if (is_string($host)) { +- $options = ParseStringFlag::IPV4_MAYBE_NON_DECIMAL +- | ParseStringFlag::IPV4SUBNET_MAYBE_COMPACT +- | ParseStringFlag::IPV4ADDRESS_MAYBE_NON_QUAD_DOTTED +- | ParseStringFlag::MAY_INCLUDE_ZONEID; +- + $host = trim($host, '[]'); + +- // IPLib does not seem to work with IPv6 syntax for IPv4 addresses ++ /* IPv4-mapped IPv6 addresses (RFC4291 2.5.5) */ + $host = preg_replace('/^::ffff:/i', '', $host); + + if (preg_match('/([0-9a-f.-]+)\.nip\.io$/i', $host, $matches)) { + $host = trim($matches[1], '-.'); + } + ++ if (strpos($host, ':') !== false && ($n = strpos($host, '%')) > 0) { ++ /* drop the zone ID */ ++ $host = substr($host, 0, $n); ++ } ++ + // TODO: This is pretty fast, but a single message can contain multiple links + // to the same target, maybe we should do some in-memory caching. +- if ($address = Factory::parseAddressString($host, $options)) { +- $nets = [ +- '0.0.0.0', - '127.0.0.0/8', // loopback - '10.0.0.0/8', // RFC1918 - '172.16.0.0/12', // RFC1918 @@ -51,6 +181,9 @@ - '169.254.0.0/16', // link-local / cloud metadata - '::1/128', - 'fc00::/7', ++ if (is_string($address = \rcube_utils::inet_pton2($host))) { ++ $nets = [ ++ ['0.0.0.0', '0.0.0.0'], + ['127.0.0.0', '127.255.255.255'], // loopback + ['10.0.0.0', '10.255.255.255'], // RFC1918 + ['172.16.0.0', '172.31.255.255'], // RFC1918 @@ -78,15 +211,98 @@ return true; } } -- - return false; - } - diff --git a/tests/Framework/Utils.php b/tests/Framework/Utils.php -index 8a95001..1a24826 100644 +index d654802..a74249d 100644 --- a/tests/Framework/Utils.php +++ b/tests/Framework/Utils.php -@@ -571,12 +571,18 @@ class Framework_Utils extends PHPUnit\Framework\TestCase +@@ -557,6 +557,86 @@ class Framework_Utils extends PHPUnit\Framework\TestCase + } + } + ++ /** ++ * Test inet_pton2() ++ * ++ * @dataProvider provide_inet_pton2_cases ++ */ ++ #[DataProvider('provide_inet_pton2_cases')] ++ public function test_inet_pton2($input, $output) ++ { ++ $r = \rcube_utils::inet_pton2($input); ++ if (is_bool($output)) { ++ $this->assertSame($output, $r); ++ } else { ++ $this->assertTrue(is_string($r)); ++ $addr = @inet_pton($output); ++ $this->assertSame($r, $addr, bin2hex($r) . " != " . bin2hex($addr)); ++ } ++ } ++ ++ /** ++ * Test-Cases for inet_pton2() test ++ */ ++ public static function provide_inet_pton2_cases(): iterable ++ { ++ return [ ++ ['', false], ++ ['0xx', false], ++ ['08', false], ++ ['a', false], ++ ['0.0.0.0.0', false], ++ ['0..0', false], ++ ['0.', false], ++ ['.0', false], ++ ['256.0', false], ++ ['0x100.0', false], ++ ['0400.0', false], ++ ['4294967296', false], ++ ['9999999999', false], ++ ['18446744073709551616', false], ++ ['040000000000', false], ++ ['077777777777', false], ++ ['0x100000000', false], ++ [' 123', false], ++ ['123 ', false], ++ ['-1', false], ++ ++ ['0', '0.0.0.0'], ++ ['0x0', '0.0.0.0'], ++ ['0x', '0.0.0.0'], ++ ['00', '0.0.0.0'], ++ ['123', '0.0.0.123'], ++ ['0xF', '0.0.0.15'], ++ ['0xFA', '0.0.0.250'], ++ ['061', '0.0.0.49'], ++ ['12345', '0.0.48.57'], ++ ['0X89AB', '0.0.137.171'], ++ ['0x89ABC', '0.8.154.188'], ++ ['012345', '0.0.20.229'], ++ ['1234567', '0.18.214.135'], ++ ['0xabcde', '0.10.188.222'], ++ ['01234567', '0.5.57.119'], ++ ['123456789', '7.91.205.21'], ++ ['0xdeadbeef', '222.173.190.239'], ++ ['07654321012', '62.177.162.10'], ++ ['4294967295', '255.255.255.255'], ++ ['2147483648', '128.0.0.0'], ++ ['0xfffefdfc', '255.254.253.252'], ++ ['037777777777', '255.255.255.255'], ++ ['020000000000', '128.0.0.0'], ++ ['226.000.000.037', '226.0.0.31'], ++ ['0x7f.1', '127.0.0.1'], ++ ['0x7f.256', '127.0.1.0'], ++ ['0x7f.0.256', '127.0.1.0'], ++ ['0377.0xfedc', '255.0.254.220'], ++ ['0x7f.0377.12345', '127.255.48.57'], ++ ['1.2.3.4', '1.2.3.4'], ++ ['0.1.2.3', '0.1.2.3'], ++ ['7.010.0x.0xa', '7.8.0.10'], ++ ]; ++ } ++ + /** + * Test is_local_url() + * +@@ -576,12 +656,17 @@ class Framework_Utils extends PHPUnit\Framework\TestCase return [ // Local hosts ['https://127.0.0.1', true], @@ -96,12 +312,11 @@ ['https://192.168.0.100', true], ['https://169.254.0.200', true], ['http://[fc00::1]', true], ++ ['http://[fc00::1%1]', true], ['ftp://[::1]:8080', true], + ['https://[127.0.0.1]', true], + ['https://[::127.0.0.1]', true], -+ ['https://[::127.0.0.001]', true], + ['https://[::ffff:192.168.1.2]', true], -+ ['https://[::ffff:192.168.01.002]', true], ['//127.0.0.1', true], ['http://localhost', true], ['http://localhost.localdomain', true], diff -Nru roundcube-1.6.5+dfsg/debian/patches/CVE-2026-48842.patch roundcube-1.6.5+dfsg/debian/patches/CVE-2026-48842.patch --- roundcube-1.6.5+dfsg/debian/patches/CVE-2026-48842.patch 1970-01-01 00:00:00.000000000 +0000 +++ roundcube-1.6.5+dfsg/debian/patches/CVE-2026-48842.patch 2026-05-25 23:08:43.000000000 +0000 @@ -0,0 +1,55 @@ +From: Aleksander Machniak +Date: Sun, 24 May 2026 09:16:47 +0200 +Subject: Fix pre-auth SQL injection in virtuser_query plugin via preg_replace + backslash escape bypass + +Origin: https://github.com/roundcube/roundcubemail/commit/87124cc7136a48b5fa9d2b40dfead6e9dcaeaf4b +Bug: https://roundcube.net/news/2026/05/24/security-updates-1.6.16-and-1.7.1 +Bug-Debian: https://bugs.debian.org/1137507 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2026-48842 +--- + plugins/virtuser_query/virtuser_query.php | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/plugins/virtuser_query/virtuser_query.php b/plugins/virtuser_query/virtuser_query.php +index 11698c3..7414302 100644 +--- a/plugins/virtuser_query/virtuser_query.php ++++ b/plugins/virtuser_query/virtuser_query.php +@@ -63,8 +63,8 @@ class virtuser_query extends rcube_plugin + { + $dbh = $this->get_dbh(); + +- $sql_result = $dbh->query(preg_replace('/%u/', $dbh->escape($p['user']), $this->config['email'])); +- $result = []; ++ $sql_result = $dbh->query(str_replace('%u', $dbh->escape($p['user']), $this->config['email'])); ++ $result = []; + + while ($sql_arr = $dbh->fetch_array($sql_result)) { + if (strpos($sql_arr[0], '@')) { +@@ -101,7 +101,7 @@ class virtuser_query extends rcube_plugin + { + $dbh = $this->get_dbh(); + +- $sql_result = $dbh->query(preg_replace('/%m/', $dbh->escape($p['email']), $this->config['user'])); ++ $sql_result = $dbh->query(str_replace('%m', $dbh->escape($p['email']), $this->config['user'])); + + if ($sql_arr = $dbh->fetch_array($sql_result)) { + $p['user'] = $sql_arr[0]; +@@ -117,7 +117,7 @@ class virtuser_query extends rcube_plugin + { + $dbh = $this->get_dbh(); + +- $sql_result = $dbh->query(preg_replace('/%u/', $dbh->escape($p['user']), $this->config['host'])); ++ $sql_result = $dbh->query(str_replace('%u', $dbh->escape($p['user']), $this->config['host'])); + + if ($sql_arr = $dbh->fetch_array($sql_result)) { + $p['host'] = $sql_arr[0]; +@@ -133,7 +133,7 @@ class virtuser_query extends rcube_plugin + { + $dbh = $this->get_dbh(); + +- $sql_result = $dbh->query(preg_replace('/%u/', $dbh->escape($p['user']), $this->config['alias'])); ++ $sql_result = $dbh->query(str_replace('%u', $dbh->escape($p['user']), $this->config['alias'])); + + if ($sql_arr = $dbh->fetch_array($sql_result)) { + $p['user'] = $sql_arr[0]; diff -Nru roundcube-1.6.5+dfsg/debian/patches/CVE-2026-48843.patch roundcube-1.6.5+dfsg/debian/patches/CVE-2026-48843.patch --- roundcube-1.6.5+dfsg/debian/patches/CVE-2026-48843.patch 1970-01-01 00:00:00.000000000 +0000 +++ roundcube-1.6.5+dfsg/debian/patches/CVE-2026-48843.patch 2026-05-25 23:08:43.000000000 +0000 @@ -0,0 +1,86 @@ +From: Aleksander Machniak +Date: Sun, 24 May 2026 09:19:25 +0200 +Subject: Fix SSRF bypass via specific local address URLs + +Origin: https://github.com/roundcube/roundcubemail/commit/cb3fc9041e91640ba9ba49ee7b2147c176ebf5a1 +Bug: https://roundcube.net/news/2026/05/24/security-updates-1.6.16-and-1.7.1 +Bug-Debian: https://bugs.debian.org/1137507 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2026-48843 +--- + program/lib/Roundcube/rcube_utils.php | 21 +++++++++++++++++++-- + tests/Framework/Utils.php | 10 ++++++++++ + 2 files changed, 29 insertions(+), 2 deletions(-) + +diff --git a/program/lib/Roundcube/rcube_utils.php b/program/lib/Roundcube/rcube_utils.php +index 8ff1db8..d1fbbb2 100644 +--- a/program/lib/Roundcube/rcube_utils.php ++++ b/program/lib/Roundcube/rcube_utils.php +@@ -1,6 +1,7 @@ + +Date: Sun, 24 May 2026 09:24:18 +0200 +Subject: Fix code injection vulnerability - remove support for code + evaluation in LDAP `autovalues` option + +Origin: https://github.com/roundcube/roundcubemail/commit/ea1798a6fbf060abcc0ba73b2435036bf8016a5a +Bug: https://roundcube.net/news/2026/05/24/security-updates-1.6.16-and-1.7.1 +Bug-Debian: https://bugs.debian.org/1137507 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2026-48844 +--- + config/defaults.inc.php | 3 +-- + program/lib/Roundcube/rcube_ldap.php | 32 ++++++-------------------------- + 2 files changed, 7 insertions(+), 28 deletions(-) + +diff --git a/config/defaults.inc.php b/config/defaults.inc.php +index 65a8214..0a691a1 100644 +--- a/config/defaults.inc.php ++++ b/config/defaults.inc.php +@@ -1142,8 +1142,7 @@ $config['ldap_public']['Verisign'] = [ + 'sub_fields' => [], + // Generate values for the following LDAP attributes automatically when creating a new record + 'autovalues' => [ +- // 'uid' => 'md5(microtime())', // You may specify PHP code snippets which are then eval'ed +- // 'mail' => '{givenname}.{sn}@mydomain.com', // or composite strings with placeholders for existing attributes ++ // 'mail' => '{givenname}.{sn}@mydomain.com', // composite strings with placeholders for existing attributes + ], + 'sort' => 'cn', // The field to sort the listing by. + 'scope' => 'sub', // search mode: sub|base|list +diff --git a/program/lib/Roundcube/rcube_ldap.php b/program/lib/Roundcube/rcube_ldap.php +index cee84f8..82d3710 100644 +--- a/program/lib/Roundcube/rcube_ldap.php ++++ b/program/lib/Roundcube/rcube_ldap.php +@@ -1581,34 +1581,14 @@ class rcube_ldap extends rcube_addressbook + + foreach ($this->prop['autovalues'] as $lf => $templ) { + if (empty($attrs[$lf])) { +- if (strpos($templ, '(') !== false) { +- // replace {attr} placeholders with (escaped!) attribute values to be safely eval'd +- $code = preg_replace('/\{\w+\}/', '', strtr($templ, array_map('addslashes', $attrvals))); +- $res = false; +- +- try { +- $res = eval("return ($code);"); +- } +- catch (ParseError $e) { +- // ignore +- } +- +- if ($res === false) { +- rcube::raise_error([ +- 'code' => 505, 'file' => __FILE__, 'line' => __LINE__, +- 'message' => "Expression parse error on: ($code)" +- ], true, false); +- continue; +- } +- +- $attrs[$lf] = $res; +- } +- else { +- // replace {attr} placeholders with concrete attribute values +- $attrs[$lf] = preg_replace('/\{\w+\}/', '', strtr($templ, $attrvals)); +- } ++ // replace {attr} placeholders with concrete attribute values ++ $attrs[$lf] = preg_replace('/\{\w+\}/', '', strtr($templ, $attrvals)); + } + } ++ ++ $rcube = rcube::get_instance(); ++ $plugin = $rcube->plugins->exec_hook('ldap_autovalues', ['attrs' => $attrs]); ++ $attrs = $plugin['attrs']; + } + + /** diff -Nru roundcube-1.6.5+dfsg/debian/patches/CVE-2026-48845.patch roundcube-1.6.5+dfsg/debian/patches/CVE-2026-48845.patch --- roundcube-1.6.5+dfsg/debian/patches/CVE-2026-48845.patch 1970-01-01 00:00:00.000000000 +0000 +++ roundcube-1.6.5+dfsg/debian/patches/CVE-2026-48845.patch 2026-05-25 23:08:43.000000000 +0000 @@ -0,0 +1,39 @@ +From: Aleksander Machniak +Date: Sun, 24 May 2026 09:21:07 +0200 +Subject: Fix local/private URL fetch bypass when remote resources were not + allowed + +Origin: https://github.com/roundcube/roundcubemail/commit/7b52353653a67e6073b97d70eb94047132b78556 +Bug: https://roundcube.net/news/2026/05/24/security-updates-1.6.16-and-1.7.1 +Bug-Debian: https://bugs.debian.org/1137507 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2026-48845 +--- + program/lib/Roundcube/rcube_washtml.php | 2 +- + tests/Framework/Washtml.php | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/program/lib/Roundcube/rcube_washtml.php b/program/lib/Roundcube/rcube_washtml.php +index b32a4de..32270ce 100644 +--- a/program/lib/Roundcube/rcube_washtml.php ++++ b/program/lib/Roundcube/rcube_washtml.php +@@ -399,7 +399,7 @@ class rcube_washtml + } + + if (preg_match('/^(http|https|ftp):.+/i', $uri)) { +- if (!empty($this->config['allow_remote']) || rcube_utils::is_local_url($uri)) { ++ if (!empty($this->config['allow_remote'])) { + return $uri; + } + +diff --git a/tests/Framework/Washtml.php b/tests/Framework/Washtml.php +index f569313..7d524f4 100644 +--- a/tests/Framework/Washtml.php ++++ b/tests/Framework/Washtml.php +@@ -712,6 +712,7 @@ class Framework_Washtml extends PHPUnit\Framework\TestCase + ['', true], + ['', false], + ['', true], ++ ['', true], + ['', false], + ['

', true], + ['

', true], diff -Nru roundcube-1.6.5+dfsg/debian/patches/CVE-2026-48846.patch roundcube-1.6.5+dfsg/debian/patches/CVE-2026-48846.patch --- roundcube-1.6.5+dfsg/debian/patches/CVE-2026-48846.patch 1970-01-01 00:00:00.000000000 +0000 +++ roundcube-1.6.5+dfsg/debian/patches/CVE-2026-48846.patch 2026-05-25 23:08:43.000000000 +0000 @@ -0,0 +1,91 @@ +From: Aleksander Machniak +Date: Sun, 24 May 2026 09:20:18 +0200 +Subject: Fix bypass of remote image blocking via CSS var() + +Origin: https://github.com/roundcube/roundcubemail/commit/852350486b88b35b8544e8a630fad89e99e2150a +Bug: https://roundcube.net/news/2026/05/24/security-updates-1.6.16-and-1.7.1 +Bug-Debian: https://bugs.debian.org/1137507 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2026-48846 +--- + program/lib/Roundcube/rcube_utils.php | 15 +++++++++++---- + tests/Framework/Utils.php | 5 +++++ + tests/Framework/Washtml.php | 18 ++++++++++++------ + 3 files changed, 28 insertions(+), 10 deletions(-) + +diff --git a/program/lib/Roundcube/rcube_utils.php b/program/lib/Roundcube/rcube_utils.php +index d1fbbb2..0ddd910 100644 +--- a/program/lib/Roundcube/rcube_utils.php ++++ b/program/lib/Roundcube/rcube_utils.php +@@ -627,10 +627,17 @@ class rcube_utils + } else { + $value = ''; + foreach (self::explode_css_property_block($rule[1]) as $val) { +- if ($url_callback && preg_match('/^url\s*\(/i', $val)) { +- if (preg_match('/^url\s*\(\s*[\'"]?([^\'"\)]*)[\'"]?\s*\)/iu', $val, $match)) { +- if ($url = $url_callback($match[1])) { +- $value .= ' url(' . $url . ')'; ++ if ($url_callback && preg_match('/\burl\s*\(/i', $val)) { ++ if (preg_match_all('/(\b)url\s*\(\s*[\'"]?([^\'"\)]*)[\'"]?\s*\)/iu', $val, $matches)) { ++ foreach ($matches[2] as $idx => $url) { ++ if ($url = $url_callback($url)) { ++ $val = str_replace($matches[0][$idx], $matches[1][$idx] . "url({$url})", $val); ++ } else { ++ $val = ''; ++ } ++ } ++ if (strlen($val)) { ++ $value .= ' ' . $val; + } + } + } elseif (preg_match('/;.+/', $val)) { +diff --git a/tests/Framework/Utils.php b/tests/Framework/Utils.php +index d5da478..d654802 100644 +--- a/tests/Framework/Utils.php ++++ b/tests/Framework/Utils.php +@@ -253,6 +253,11 @@ class Framework_Utils extends PHPUnit\Framework\TestCase + $mod = \rcube_utils::mod_css_styles("p { background: url('//data:image&leak'); }", 'rcmbody'); + $this->assertSame('#rcmbody p {}', $mod); + ++ $mod = \rcube_utils::mod_css_styles("p { background-image: var(--x, url(http://evil.com/1.gif)) }", 'rcmbody'); ++ $this->assertSame('#rcmbody p {}', $mod); ++ $mod = \rcube_utils::mod_css_styles("p { background-image: var(--x, url(http://evil.com/1.gif)) }", 'rcmbody', true); ++ $this->assertSame('#rcmbody p { background-image: var(--x, url(http://evil.com/1.gif)); }', $mod); ++ + // Note: This looks to me like a bug in browsers, for now we don't allow image-set at all + $mod = \rcube_utils::mod_css_styles("p { background: image-set('//evil.com/img.png' 1x); }", 'rcmbody'); + $this->assertSame('#rcmbody p {}', $mod); +diff --git a/tests/Framework/Washtml.php b/tests/Framework/Washtml.php +index 611bcc3..f569313 100644 +--- a/tests/Framework/Washtml.php ++++ b/tests/Framework/Washtml.php +@@ -709,18 +709,24 @@ class Framework_Washtml extends PHPUnit\Framework\TestCase + function test_extlinks() + { + $html = [ +- ["", true], +- ["", false], +- ["", true], +- ["", false], +- ['

', true], ++ ['', true], ++ ['', false], ++ ['', true], ++ ['', false], ++ ['

', true], ++ ['

', true], ++ ['

', true], ++ ['

', true], ++ ['

', true], ++ ['

', true], ++ ['

', true], + ]; + + foreach ($html as $item) { + $washer = new rcube_washtml; + $washed = $washer->wash($item[0]); + +- $this->assertSame($item[1], $washer->extlinks); ++ $this->assertSame($item[1], $washer->extlinks, "Failed on: {$item[0]}"); + } + + foreach ($html as $item) { diff -Nru roundcube-1.6.5+dfsg/debian/patches/CVE-2026-48847.patch roundcube-1.6.5+dfsg/debian/patches/CVE-2026-48847.patch --- roundcube-1.6.5+dfsg/debian/patches/CVE-2026-48847.patch 1970-01-01 00:00:00.000000000 +0000 +++ roundcube-1.6.5+dfsg/debian/patches/CVE-2026-48847.patch 2026-05-25 23:08:43.000000000 +0000 @@ -0,0 +1,80 @@ +From: Aleksander Machniak +Date: Sun, 24 May 2026 09:23:23 +0200 +Subject: Fix pre-auth arbitrary file delete via redis/memcache session + poisoning bypass + +Origin: https://github.com/roundcube/roundcubemail/commit/703318e6a59515b73b0d8aa2a91e346b02f56baa +Bug: https://roundcube.net/news/2026/05/24/security-updates-1.6.16-and-1.7.1 +Bug-Debian: https://bugs.debian.org/1137507 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2026-48847 +--- + program/include/rcmail_attachment_handler.php | 11 +---------- + program/include/rcmail_sendmail.php | 12 ++---------- + 2 files changed, 3 insertions(+), 20 deletions(-) + +diff --git a/program/include/rcmail_attachment_handler.php b/program/include/rcmail_attachment_handler.php +index 2ee02e0..0eca6c0 100644 +--- a/program/include/rcmail_attachment_handler.php ++++ b/program/include/rcmail_attachment_handler.php +@@ -117,16 +117,6 @@ class rcmail_attachment_handler + $this->mimetype = rcube_mime::fix_mimetype($this->mimetype); + } + +- /** +- * Remove temp files, etc. +- */ +- public function __destruct() +- { +- if ($this->body_file) { +- @unlink($this->body_file); +- } +- } +- + /** + * Check if the object is a message part not uploaded file + * +@@ -260,6 +250,7 @@ class rcmail_attachment_handler + $this->body_file = $filename; + fclose($fp); + @chmod($filename, 0600); ++ rcmail::get_instance()->add_shutdown_function(static function () use ($filename) { @unlink($filename); }); + + return true; + } +diff --git a/program/include/rcmail_sendmail.php b/program/include/rcmail_sendmail.php +index 6b3ecfb..d202895 100644 +--- a/program/include/rcmail_sendmail.php ++++ b/program/include/rcmail_sendmail.php +@@ -76,16 +76,6 @@ class rcmail_sendmail + } + } + +- /** +- * Object destructor to cleanup temporary files +- */ +- public function __destruct() +- { +- foreach ($this->temp_files as $file) { +- @unlink($file); +- } +- } +- + /** + * Collect input data for message headers + * +@@ -461,6 +451,7 @@ class rcmail_sendmail + + if ($mailbody_file) { + $this->temp_files[$message->headers()['Message-ID']] = $mailbody_file; ++ $this->rcmail->add_shutdown_function(static function () use ($mailbody_file) { @unlink($mailbody_file); }); + } + + // save message sent time +@@ -545,6 +536,7 @@ class rcmail_sendmail + + if (!is_a($msg, 'PEAR_Error')) { + $this->temp_files[$msg_id] = $msg_file; ++ $this->rcmail->add_shutdown_function(static function () use ($msg_file) { @unlink($msg_file); }); + } + } + diff -Nru roundcube-1.6.5+dfsg/debian/patches/CVE-2026-48848.patch roundcube-1.6.5+dfsg/debian/patches/CVE-2026-48848.patch --- roundcube-1.6.5+dfsg/debian/patches/CVE-2026-48848.patch 1970-01-01 00:00:00.000000000 +0000 +++ roundcube-1.6.5+dfsg/debian/patches/CVE-2026-48848.patch 2026-05-25 23:08:43.000000000 +0000 @@ -0,0 +1,63 @@ +From: Aleksander Machniak +Date: Sun, 24 May 2026 09:15:35 +0200 +Subject: Fix CSS injection bypass in HTML sanitizer via SVG `` + +Origin: https://github.com/roundcube/roundcubemail/commit/58e5263f341e6a418774fb6d2643669a3c4d8a27 +Bug: https://roundcube.net/news/2026/05/24/security-updates-1.6.16-and-1.7.1 +Bug-Debian: https://bugs.debian.org/1137507 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2026-48848 +--- + program/lib/Roundcube/rcube_washtml.php | 14 ++++++++++---- + tests/Framework/Washtml.php | 12 ++++++++++++ + 2 files changed, 22 insertions(+), 4 deletions(-) + +diff --git a/program/lib/Roundcube/rcube_washtml.php b/program/lib/Roundcube/rcube_washtml.php +index 922a5da..b32a4de 100644 +--- a/program/lib/Roundcube/rcube_washtml.php ++++ b/program/lib/Roundcube/rcube_washtml.php +@@ -293,11 +293,17 @@ class rcube_washtml + $key = strtolower($name); + $value = $attr->nodeValue; + +- if ($key == 'style' && ($style = $this->wash_style($value))) { +- // replace double quotes to prevent syntax error and XSS issues (#1490227) +- $result .= ' style="' . str_replace('"', '"', $style) . '"'; ++ if ($key == 'style' || ($key == 'values' && self::attribute_value($node, 'attributename', '/^style$/i'))) { ++ $style = ''; ++ if ($value === '' || ($style = $this->wash_style($value))) { ++ // replace double quotes to prevent syntax error and XSS issues (#1490227) ++ $result .= ' ' . $attr->nodeName . '="' . str_replace('"', '"', $style) . '"'; ++ } ++ else { ++ $washed[] = htmlspecialchars($attr->nodeName, \ENT_QUOTES, $this->config['charset']); ++ } + } +- else if (isset($this->_html_attribs[$key]) || in_array($key, $additional_attribs)) { ++ elseif (isset($this->_html_attribs[$key]) || in_array($key, $additional_attribs)) { + $value = trim($value); + $out = null; + +diff --git a/tests/Framework/Washtml.php b/tests/Framework/Washtml.php +index ec1dd5d..611bcc3 100644 +--- a/tests/Framework/Washtml.php ++++ b/tests/Framework/Washtml.php +@@ -525,6 +525,18 @@ class Framework_Washtml extends PHPUnit\Framework\TestCase + '', + '', + ], ++ [ ++ '', ++ '', ++ ], ++ [ ++ '', ++ '', ++ ], ++ [ ++ '', ++ '', ++ ], + ]; + } + diff -Nru roundcube-1.6.5+dfsg/debian/patches/CVE-2026-48849.patch roundcube-1.6.5+dfsg/debian/patches/CVE-2026-48849.patch --- roundcube-1.6.5+dfsg/debian/patches/CVE-2026-48849.patch 1970-01-01 00:00:00.000000000 +0000 +++ roundcube-1.6.5+dfsg/debian/patches/CVE-2026-48849.patch 2026-05-25 23:08:43.000000000 +0000 @@ -0,0 +1,26 @@ +From: Aleksander Machniak +Date: Sun, 24 May 2026 09:34:27 +0200 +Subject: Fix stored XSS/HTML/CSS injection in subject field of the draft + restore dialog + +Origin: https://github.com/roundcube/roundcubemail/commit/a21519187873ce962db029b6ff68e47bd7f3fd8a +Bug: https://roundcube.net/news/2026/05/24/security-updates-1.6.16-and-1.7.1 +Bug-Debian: https://bugs.debian.org/1137507 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2026-48849 +--- + program/js/app.js | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/program/js/app.js b/program/js/app.js +index 16dcbb4..b8a51ff 100644 +--- a/program/js/app.js ++++ b/program/js/app.js +@@ -4718,7 +4718,7 @@ function rcube_webmail() + this.show_popup_dialog( + this.get_label('restoresavedcomposedata') + .replace('$date', new Date(formdata.changed).toLocaleString()) +- .replace('$subject', formdata._subject) ++ .replace('$subject', $('').text(formdata._subject).html()) + .replace(/\n/g, '
'), + this.get_label('restoremessage'), + [{ diff -Nru roundcube-1.6.5+dfsg/debian/patches/series roundcube-1.6.5+dfsg/debian/patches/series --- roundcube-1.6.5+dfsg/debian/patches/series 2026-03-20 18:15:19.000000000 +0000 +++ roundcube-1.6.5+dfsg/debian/patches/series 2026-05-25 23:08:43.000000000 +0000 @@ -46,5 +46,13 @@ CVE-2026-35544.patch CVE-2026-35539.patch CVE-2026-35540.patch -Avoid-dependency-on-new-package-mlocati-ip-lib.patch CVE-2026-35545.patch +CVE-2026-48849.patch +CVE-2026-48848.patch +CVE-2026-48842.patch +CVE-2026-48843.patch +CVE-2026-48846.patch +CVE-2026-48845.patch +CVE-2026-48847.patch +CVE-2026-48844.patch +Avoid-dependency-on-new-package-mlocati-ip-lib.patch