Control: retitle -1 roundcube: [CVE-2026-26079] CSS injection vulnerability and [CVE-2026-25916] remote image blocking bypass
Hi, Thanks for the update! Here are tested debdiffs for trixie-security and bookworm-security. As for the previous upload, I suggest to follow 1.6.x for trixie-security (the upstream diff [0] is pretty targeted already) and backport targeted fixes for bookworm-security. Cheers -- Guilhem. [0] https://github.com/roundcube/roundcubemail/compare/1.6.12...1.6.13
diffstat for roundcube-1.6.12+dfsg roundcube-1.6.13+dfsg CHANGELOG.md | 6 debian/changelog | 9 debian/patches/Fix-FTBFS-with-phpunit-11.patch | 121 ++++------ plugins/managesieve/Changelog | 1 plugins/managesieve/lib/Roundcube/rcube_sieve_vacation.php | 8 program/lib/Roundcube/rcube_utils.php | 64 +++-- program/lib/Roundcube/rcube_washtml.php | 3 public_html/plugins/managesieve/Changelog | 1 public_html/plugins/managesieve/lib/Roundcube/rcube_sieve_vacation.php | 8 tests/Framework/Utils.php | 16 + tests/Framework/Washtml.php | 8 11 files changed, 160 insertions(+), 85 deletions(-) diff -Nru roundcube-1.6.12+dfsg/CHANGELOG.md roundcube-1.6.13+dfsg/CHANGELOG.md --- roundcube-1.6.12+dfsg/CHANGELOG.md 2025-12-14 09:10:51.000000000 +0100 +++ roundcube-1.6.13+dfsg/CHANGELOG.md 2026-02-08 10:25:02.000000000 +0100 @@ -2,6 +2,12 @@ ## Unreleased +- Managesieve: Fix handling of string-list format values for date tests in Out of Office (#10075) +- Fix remote image blocking bypass via SVG content reported by nullcathedral +- Fix CSS injection vulnerability reported by CERT Polska + +## Release 1.6.12 + - Support IPv6 in database DSN (#9937) - Don't force specific error_reporting setting - Fix compatibility with PHP 8.5 regarding array_first() diff -Nru roundcube-1.6.12+dfsg/debian/changelog roundcube-1.6.13+dfsg/debian/changelog --- roundcube-1.6.12+dfsg/debian/changelog 2025-12-14 11:51:43.000000000 +0100 +++ roundcube-1.6.13+dfsg/debian/changelog 2026-02-11 10:55:46.000000000 +0100 @@ -1,3 +1,12 @@ +roundcube (1.6.13+dfsg-0+deb13u1) trixie-security; urgency=high + + * New upstream security and bugfix release (closes: #1127447). + + Fix CVE-2026-26079: CSS injection vulnerability. + + Fix CVE-2026-25916: Remote image blocking bypass via SVG content. + * Refresh d/patches. + + -- Guilhem Moulin <[email protected]> Wed, 11 Feb 2026 10:55:46 +0100 + roundcube (1.6.12+dfsg-0+deb13u1) trixie-security; urgency=high * New upstream security and bugfix release (closes: #1122899). diff -Nru roundcube-1.6.12+dfsg/debian/patches/Fix-FTBFS-with-phpunit-11.patch roundcube-1.6.13+dfsg/debian/patches/Fix-FTBFS-with-phpunit-11.patch --- roundcube-1.6.12+dfsg/debian/patches/Fix-FTBFS-with-phpunit-11.patch 2025-12-14 11:51:43.000000000 +0100 +++ roundcube-1.6.13+dfsg/debian/patches/Fix-FTBFS-with-phpunit-11.patch 2026-02-11 10:55:46.000000000 +0100 @@ -41,7 +41,7 @@ plugins/managesieve/tests/Forward.php | 16 +- plugins/managesieve/tests/Managesieve.php | 14 +- plugins/managesieve/tests/Script.php | 17 +- - plugins/managesieve/tests/Vacation.php | 21 +- + plugins/managesieve/tests/Vacation.php | 21 ++- plugins/markasjunk/tests/Markasjunk.php | 22 ++- plugins/new_user_dialog/tests/NewUserDialog.php | 14 +- .../new_user_identity/tests/NewUserIdentity.php | 14 +- @@ -76,9 +76,9 @@ tests/Actions/Contacts/Qrcode.php | 17 +- tests/Actions/Contacts/Save.php | 27 +-- tests/Actions/Contacts/Search.php | 18 +- - tests/Actions/Contacts/SearchCreate.php | 21 +- - tests/Actions/Contacts/SearchDelete.php | 21 +- - tests/Actions/Contacts/Show.php | 21 +- + tests/Actions/Contacts/SearchCreate.php | 21 ++- + tests/Actions/Contacts/SearchDelete.php | 21 ++- + tests/Actions/Contacts/Show.php | 21 ++- tests/Actions/Contacts/Undo.php | 15 +- tests/Actions/Contacts/UploadPhoto.php | 19 +- tests/Actions/Login/Oauth.php | 14 +- @@ -149,7 +149,7 @@ tests/ExitException.php | 6 +- tests/Framework/Addressbook.php | 40 ++-- tests/Framework/Addresses.php | 16 +- - tests/Framework/BaseReplacer.php | 21 +- + tests/Framework/BaseReplacer.php | 21 ++- tests/Framework/Bootstrap.php | 8 +- tests/Framework/Browser.php | 34 ++-- tests/Framework/Cache.php | 18 +- @@ -201,7 +201,7 @@ tests/Framework/Text2Html.php | 22 ++- tests/Framework/TnefDecoder.php | 16 +- tests/Framework/User.php | 30 +-- - tests/Framework/Utils.php | 211 +++++++++++---------- + tests/Framework/Utils.php | 209 +++++++++++---------- tests/Framework/VCard.php | 40 ++-- tests/Framework/Washtml.php | 85 +++++---- tests/OutputHtmlMock.php | 6 +- @@ -221,8 +221,8 @@ tests/Rcmail/Utils.php | 22 ++- tests/StderrMock.php | 15 +- tests/StorageMock.php | 4 +- - tests/bootstrap.php | 21 +- - 213 files changed, 2503 insertions(+), 1797 deletions(-) + tests/bootstrap.php | 21 ++- + 213 files changed, 2502 insertions(+), 1796 deletions(-) diff --git a/plugins/acl/tests/Acl.php b/plugins/acl/tests/Acl.php index 94e0bd4..0ad987f 100644 @@ -10006,7 +10006,7 @@ $idents = $user->list_identities(); diff --git a/tests/Framework/Utils.php b/tests/Framework/Utils.php -index 29df81d..cf76834 100644 +index e65b5a9..8809da2 100644 --- a/tests/Framework/Utils.php +++ b/tests/Framework/Utils.php @@ -1,11 +1,15 @@ @@ -10177,7 +10177,7 @@ $this->assertSame('/* evil! */', $mod); $mod = \rcube_utils::mod_css_styles("@\\69mport url('http://localhost/somestuff/css/master.css');", 'rcmbody'); -@@ -261,47 +270,47 @@ class Framework_Utils extends PHPUnit\Framework\TestCase +@@ -261,19 +270,19 @@ class Framework_Utils extends PHPUnit\Framework\TestCase $this->assertSame('#rcmbody p { background: none !important; }', $mod); // position: fixed (#5264) @@ -10202,6 +10202,10 @@ + $mod = \rcube_utils::mod_css_styles(".test { position\n: fixed; top: 0; }", 'rcmbody'); $this->assertEquals("#rcmbody .test { position: absolute; top: 0; }", $mod, "Replace position:fixed with position:absolute (5)"); + // missing closing brace +@@ -281,27 +290,27 @@ class Framework_Utils extends PHPUnit\Framework\TestCase + $this->assertSame('#rcmbody .test { position: absolute; top: 0; }', $mod, 'Replace position:fixed with position:absolute (6)'); + // allow data URIs with images (#5580) - $mod = rcube_utils::mod_css_styles("body { background-image: url(data:image/png;base64,123); }", 'rcmbody'); + $mod = \rcube_utils::mod_css_styles("body { background-image: url(data:image/png;base64,123); }", 'rcmbody'); @@ -10232,13 +10236,8 @@ + $mod = \rcube_utils::mod_css_styles($style, 'rcmbody', true); $this->assertSame("#rcmbody { color: red; }", $mod); - $style = "body { background:url(alert('URL!')); }"; -- $mod = rcube_utils::mod_css_styles($style, 'rcmbody', true); -+ $mod = \rcube_utils::mod_css_styles($style, 'rcmbody', true); - $this->assertSame("#rcmbody {}", $mod); - } - -@@ -325,7 +334,7 @@ class Framework_Utils extends PHPUnit\Framework\TestCase + $style = 'body { background:url(alert('URL!')); }'; +@@ -335,7 +344,7 @@ class Framework_Utils extends PHPUnit\Framework\TestCase :root * { color: red; } :root > * { top: 0; } '; @@ -10247,7 +10246,7 @@ $this->assertStringContainsString('#rc .testone', $mod); $this->assertStringContainsString('#rc .testthree.testfour', $mod); -@@ -343,24 +352,24 @@ class Framework_Utils extends PHPUnit\Framework\TestCase +@@ -353,24 +362,24 @@ class Framework_Utils extends PHPUnit\Framework\TestCase function test_xss_entity_decode() { @@ -10277,7 +10276,7 @@ { return [ [ -@@ -435,9 +444,10 @@ class Framework_Utils extends PHPUnit\Framework\TestCase +@@ -445,9 +454,10 @@ class Framework_Utils extends PHPUnit\Framework\TestCase * * @dataProvider data_parse_css_block */ @@ -10289,7 +10288,7 @@ } /** -@@ -452,7 +462,7 @@ class Framework_Utils extends PHPUnit\Framework\TestCase +@@ -462,7 +472,7 @@ class Framework_Utils extends PHPUnit\Framework\TestCase ]; foreach ($data as $text => $res) { @@ -10298,7 +10297,7 @@ $this->assertSame($res, $result); } } -@@ -465,7 +475,7 @@ class Framework_Utils extends PHPUnit\Framework\TestCase +@@ -475,7 +485,7 @@ class Framework_Utils extends PHPUnit\Framework\TestCase $data = ['', 'a,b,c', 'a', ',', ',a']; foreach ($data as $text) { @@ -10307,7 +10306,7 @@ $this->assertSame(explode(',', $text), $result); } } -@@ -480,7 +490,7 @@ class Framework_Utils extends PHPUnit\Framework\TestCase +@@ -490,7 +500,7 @@ class Framework_Utils extends PHPUnit\Framework\TestCase ]; foreach ($input as $idx => $value) { @@ -10316,7 +10315,7 @@ } $input = [ -@@ -488,7 +498,7 @@ class Framework_Utils extends PHPUnit\Framework\TestCase +@@ -498,7 +508,7 @@ class Framework_Utils extends PHPUnit\Framework\TestCase ]; foreach ($input as $idx => $value) { @@ -10325,7 +10324,7 @@ } } -@@ -498,13 +508,13 @@ class Framework_Utils extends PHPUnit\Framework\TestCase +@@ -508,13 +518,13 @@ class Framework_Utils extends PHPUnit\Framework\TestCase function test_get_input_string() { $_GET = []; @@ -10342,7 +10341,7 @@ } /** -@@ -512,18 +522,18 @@ class Framework_Utils extends PHPUnit\Framework\TestCase +@@ -522,18 +532,18 @@ class Framework_Utils extends PHPUnit\Framework\TestCase */ function test_is_simple_string() { @@ -10373,7 +10372,7 @@ } /** -@@ -538,7 +548,7 @@ class Framework_Utils extends PHPUnit\Framework\TestCase +@@ -548,7 +558,7 @@ class Framework_Utils extends PHPUnit\Framework\TestCase ]; foreach ($test as $v) { @@ -10382,7 +10381,7 @@ $this->assertSame($v[2], $result); } } -@@ -568,7 +578,7 @@ class Framework_Utils extends PHPUnit\Framework\TestCase +@@ -578,7 +588,7 @@ class Framework_Utils extends PHPUnit\Framework\TestCase ]; foreach ($test as $datetime => $ts) { @@ -10391,7 +10390,7 @@ $this->assertSame($ts, $result, "Error parsing date: $datetime"); } } -@@ -595,7 +605,7 @@ class Framework_Utils extends PHPUnit\Framework\TestCase +@@ -605,7 +615,7 @@ class Framework_Utils extends PHPUnit\Framework\TestCase ]; foreach ($test as $datetime => $ts) { @@ -10400,7 +10399,7 @@ $this->assertSame($ts, $result ? $result->format('Y-m-d') : false, "Error parsing date: $datetime"); } -@@ -605,7 +615,7 @@ class Framework_Utils extends PHPUnit\Framework\TestCase +@@ -615,7 +625,7 @@ class Framework_Utils extends PHPUnit\Framework\TestCase ]; foreach ($test as $datetime => $ts) { @@ -10409,7 +10408,7 @@ $this->assertSame($ts, $result ? $result->format('Y-m-d H:i:s') : false, "Error parsing date: $datetime"); } -@@ -614,7 +624,7 @@ class Framework_Utils extends PHPUnit\Framework\TestCase +@@ -624,7 +634,7 @@ class Framework_Utils extends PHPUnit\Framework\TestCase ]; foreach ($test as $datetime => $ts) { @@ -10418,7 +10417,7 @@ $this->assertSame($ts, $result ? $result->format('Y-m-d H:i:s O') : false, "Error parsing date: $datetime"); } } -@@ -624,17 +634,17 @@ class Framework_Utils extends PHPUnit\Framework\TestCase +@@ -634,17 +644,17 @@ class Framework_Utils extends PHPUnit\Framework\TestCase */ function test_anytodatetime_timezone() { @@ -10439,7 +10438,7 @@ if ($result) $result->setTimezone($tz); // move to target timezone for comparison $this->assertSame($ts, $result ? $result->format('Y-m-d H:i') : false, "Error parsing date: $datetime"); } -@@ -653,7 +663,7 @@ class Framework_Utils extends PHPUnit\Framework\TestCase +@@ -663,7 +673,7 @@ class Framework_Utils extends PHPUnit\Framework\TestCase ]; foreach ($test as $data) { @@ -10448,7 +10447,7 @@ $this->assertSame($data[2], $result, "Error formatting date: " . $data[0]); } } -@@ -672,7 +682,7 @@ class Framework_Utils extends PHPUnit\Framework\TestCase +@@ -682,7 +692,7 @@ class Framework_Utils extends PHPUnit\Framework\TestCase ]; foreach ($test as $input => $output) { @@ -10457,7 +10456,7 @@ $this->assertSame($output, $result); } } -@@ -697,7 +707,7 @@ class Framework_Utils extends PHPUnit\Framework\TestCase +@@ -707,7 +717,7 @@ class Framework_Utils extends PHPUnit\Framework\TestCase ]; foreach ($test as $input => $output) { @@ -10466,7 +10465,7 @@ $this->assertSame($output, $result, "Error normalizing '$input'"); } } -@@ -720,7 +730,7 @@ class Framework_Utils extends PHPUnit\Framework\TestCase +@@ -730,7 +740,7 @@ class Framework_Utils extends PHPUnit\Framework\TestCase ]; foreach ($test as $idx => $params) { @@ -10475,7 +10474,7 @@ $this->assertSame($params[2], $result, "words_match() at index $idx"); } } -@@ -746,7 +756,7 @@ class Framework_Utils extends PHPUnit\Framework\TestCase +@@ -756,7 +766,7 @@ class Framework_Utils extends PHPUnit\Framework\TestCase } foreach ($test as $input => $output) { @@ -10484,7 +10483,7 @@ $this->assertSame($output, $result); } } -@@ -756,17 +766,17 @@ class Framework_Utils extends PHPUnit\Framework\TestCase +@@ -766,17 +776,17 @@ class Framework_Utils extends PHPUnit\Framework\TestCase */ function test_random_bytes() { @@ -10508,7 +10507,7 @@ { /* -@@ -803,9 +813,10 @@ class Framework_Utils extends PHPUnit\Framework\TestCase +@@ -813,9 +823,10 @@ class Framework_Utils extends PHPUnit\Framework\TestCase * @param string $encoded Encoded email address * @dataProvider data_idn_convert */ @@ -10520,7 +10519,7 @@ } /** -@@ -815,9 +826,10 @@ class Framework_Utils extends PHPUnit\Framework\TestCase +@@ -825,9 +836,10 @@ class Framework_Utils extends PHPUnit\Framework\TestCase * @param string $encoded Encoded email address * @dataProvider data_idn_convert */ @@ -10532,7 +10531,7 @@ } /** -@@ -825,14 +837,14 @@ class Framework_Utils extends PHPUnit\Framework\TestCase +@@ -835,14 +847,14 @@ class Framework_Utils extends PHPUnit\Framework\TestCase */ function test_idn_to_ascii_special() { @@ -10550,7 +10549,7 @@ { return [ ['%z', 'hostname', 'hostname'], -@@ -847,15 +859,16 @@ class Framework_Utils extends PHPUnit\Framework\TestCase +@@ -857,15 +869,16 @@ class Framework_Utils extends PHPUnit\Framework\TestCase * * @dataProvider data_parse_host */ @@ -10569,7 +10568,7 @@ { return [ [['hostname', null, null], ['hostname', null, null]], -@@ -878,15 +891,16 @@ class Framework_Utils extends PHPUnit\Framework\TestCase +@@ -888,15 +901,16 @@ class Framework_Utils extends PHPUnit\Framework\TestCase * * @dataProvider data_parse_host_uri */ @@ -10588,7 +10587,7 @@ return [ ['both', 'Fwd: Re: Test subject both', 'Test subject both'], ['both', 'Re: Fwd: Test subject both', 'Test subject both'], -@@ -904,8 +918,9 @@ class Framework_Utils extends PHPUnit\Framework\TestCase +@@ -914,8 +928,9 @@ class Framework_Utils extends PHPUnit\Framework\TestCase * * @dataProvider data_remove_subject_prefix */ @@ -10599,7 +10598,7 @@ } /** -@@ -913,13 +928,13 @@ class Framework_Utils extends PHPUnit\Framework\TestCase +@@ -923,13 +938,13 @@ class Framework_Utils extends PHPUnit\Framework\TestCase */ function test_server_name() { @@ -10616,7 +10615,7 @@ } /** -@@ -929,31 +944,31 @@ class Framework_Utils extends PHPUnit\Framework\TestCase +@@ -939,31 +954,31 @@ class Framework_Utils extends PHPUnit\Framework\TestCase { $_SERVER['test'] = 'test.com'; @@ -10815,7 +10814,7 @@ $this->assertSame($result, "BEGIN:VCARD\r\nVERSION:3.0\r\nFN:\r\nN:;;;;\r\nEND:VCARD"); diff --git a/tests/Framework/Washtml.php b/tests/Framework/Washtml.php -index 0b9e1e9..a3a6d5b 100644 +index ef324f8..e8e5a4a 100644 --- a/tests/Framework/Washtml.php +++ b/tests/Framework/Washtml.php @@ -1,11 +1,14 @@ @@ -11016,7 +11015,7 @@ { $svg1 = "<svg id='x' width='100' height='100'><a xlink:href='javascript:alert(1)'><rect x='0' y='0' width='100' height='100' /></a></svg>"; -@@ -500,9 +503,10 @@ class Framework_Washtml extends PHPUnit\Framework\TestCase +@@ -508,9 +511,10 @@ class Framework_Washtml extends PHPUnit\Framework\TestCase * * @dataProvider data_wash_svg_tests */ @@ -11028,7 +11027,7 @@ $washed = $washer->wash($input); $this->assertSame($expected, $this->cleanupResult($washed), "SVG content"); -@@ -511,7 +515,7 @@ class Framework_Washtml extends PHPUnit\Framework\TestCase +@@ -519,7 +523,7 @@ class Framework_Washtml extends PHPUnit\Framework\TestCase /** * Test cases for various XSS issues */ @@ -11037,7 +11036,7 @@ { return [ [ -@@ -566,9 +570,10 @@ class Framework_Washtml extends PHPUnit\Framework\TestCase +@@ -574,9 +578,10 @@ class Framework_Washtml extends PHPUnit\Framework\TestCase * * @dataProvider data_wash_xss_tests */ @@ -11049,7 +11048,7 @@ $washed = $washer->wash($input); $this->assertSame($expected, $this->cleanupResult($washed), "XSS issues"); -@@ -582,7 +587,7 @@ class Framework_Washtml extends PHPUnit\Framework\TestCase +@@ -590,7 +595,7 @@ class Framework_Washtml extends PHPUnit\Framework\TestCase $html = "<img style='position:fixed' /><img style=\"position:/**/ fixed; top:10px\" />"; $exp = "<img style=\"position: absolute\" /><img style=\"position: absolute; top: 10px\" />"; @@ -11058,7 +11057,7 @@ $washed = $washer->wash($html); $this->assertTrue(strpos($washed, $exp) !== false, "Position:fixed (#5264)"); -@@ -626,7 +631,7 @@ class Framework_Washtml extends PHPUnit\Framework\TestCase +@@ -634,7 +639,7 @@ class Framework_Washtml extends PHPUnit\Framework\TestCase <annotation encoding="TeX">I_D = \frac{1}{2} k_n \frac{W}{L} (V_{GS}-V_t)^2</annotation> </semantics></math>'; @@ -11067,7 +11066,7 @@ $washed = $washer->wash($mathml); // remove whitespace between tags -@@ -643,7 +648,7 @@ class Framework_Washtml extends PHPUnit\Framework\TestCase +@@ -651,7 +656,7 @@ class Framework_Washtml extends PHPUnit\Framework\TestCase { $html = "<input type=\"image\" src=\"http://TRACKING_URL/\">"; @@ -11076,7 +11075,7 @@ $washed = $washer->wash($html); $this->assertTrue($washer->extlinks); -@@ -651,7 +656,7 @@ class Framework_Washtml extends PHPUnit\Framework\TestCase +@@ -659,7 +664,7 @@ class Framework_Washtml extends PHPUnit\Framework\TestCase $html = "<video src=\"http://TRACKING_URL/\">"; @@ -11085,7 +11084,7 @@ $washed = $washer->wash($html); $this->assertTrue($washer->extlinks); -@@ -672,14 +677,14 @@ class Framework_Washtml extends PHPUnit\Framework\TestCase +@@ -680,14 +685,14 @@ class Framework_Washtml extends PHPUnit\Framework\TestCase ]; foreach ($html as $item) { @@ -11102,7 +11101,7 @@ $washed = $washer->wash($item[0]); $this->assertFalse($washer->extlinks); -@@ -690,7 +695,7 @@ class Framework_Washtml extends PHPUnit\Framework\TestCase +@@ -698,7 +703,7 @@ class Framework_Washtml extends PHPUnit\Framework\TestCase { $html = '<textarea><p style="x:</textarea><img src=x onerror=alert(1)>">'; @@ -11111,7 +11110,7 @@ $washed = $washer->wash($html); $this->assertStringNotContainsString('onerror=alert(1)>', $washed); -@@ -702,7 +707,7 @@ class Framework_Washtml extends PHPUnit\Framework\TestCase +@@ -710,7 +715,7 @@ class Framework_Washtml extends PHPUnit\Framework\TestCase */ function test_css_prefix() { @@ -11120,7 +11119,7 @@ $html = '<p id="my-id">' . '<label for="my-other-id" class="my-class1 my-class2">test</label>' -@@ -730,14 +735,14 @@ class Framework_Washtml extends PHPUnit\Framework\TestCase +@@ -738,14 +743,14 @@ class Framework_Washtml extends PHPUnit\Framework\TestCase { $html = '<p><?xml:namespace prefix = "xsl" /></p>'; @@ -11137,7 +11136,7 @@ $washed = $this->cleanupResult($washer->wash($html)); $this->assertSame($washed, 'HTML'); -@@ -748,7 +753,7 @@ class Framework_Washtml extends PHPUnit\Framework\TestCase +@@ -756,7 +761,7 @@ class Framework_Washtml extends PHPUnit\Framework\TestCase */ function test_missing_tags() { @@ -11146,7 +11145,7 @@ $html = '<head></head>First line<br />Second line'; $washed = $washer->wash($html); -@@ -790,7 +795,7 @@ class Framework_Washtml extends PHPUnit\Framework\TestCase +@@ -798,7 +803,7 @@ class Framework_Washtml extends PHPUnit\Framework\TestCase { $html = '<p><![CDATA[<script>alert(document.cookie)</script>]]></p>'; @@ -11155,7 +11154,7 @@ $washed = $washer->wash($html); $this->assertTrue(strpos($washed, '<script>') === false, "CDATA content"); -@@ -802,7 +807,7 @@ class Framework_Washtml extends PHPUnit\Framework\TestCase +@@ -810,7 +815,7 @@ class Framework_Washtml extends PHPUnit\Framework\TestCase function test_resolve_base() { $html = file_get_contents(TESTS_DIR . 'src/htmlbase.txt'); @@ -11164,7 +11163,7 @@ $this->assertMatchesRegularExpression('|src="http://alec\.pl/dir/img1\.gif"|', $html, "URI base resolving [1]"); $this->assertMatchesRegularExpression('|src="http://alec\.pl/dir/img2\.gif"|', $html, "URI base resolving [2]"); -@@ -848,7 +853,7 @@ class Framework_Washtml extends PHPUnit\Framework\TestCase +@@ -856,7 +861,7 @@ class Framework_Washtml extends PHPUnit\Framework\TestCase <tr><td></td></tr> </table>'; diff -Nru roundcube-1.6.12+dfsg/plugins/managesieve/Changelog roundcube-1.6.13+dfsg/plugins/managesieve/Changelog --- roundcube-1.6.12+dfsg/plugins/managesieve/Changelog 2025-12-14 09:10:51.000000000 +0100 +++ roundcube-1.6.13+dfsg/plugins/managesieve/Changelog 2026-02-08 10:25:02.000000000 +0100 @@ -1,3 +1,4 @@ +- Fix handling of string-list format values for date tests in Out of Office (#10075) - Fix invalid line break characters in multi-line text in Sieve scripts (#9543) - Fix javascript error when relational or spamtest extension is not enabled (#9139) - Removed managesieve_usetls option (in favor of the scheme prefix in managesieve_host) diff -Nru roundcube-1.6.12+dfsg/plugins/managesieve/lib/Roundcube/rcube_sieve_vacation.php roundcube-1.6.13+dfsg/plugins/managesieve/lib/Roundcube/rcube_sieve_vacation.php --- roundcube-1.6.12+dfsg/plugins/managesieve/lib/Roundcube/rcube_sieve_vacation.php 2025-12-14 09:10:51.000000000 +0100 +++ roundcube-1.6.13+dfsg/plugins/managesieve/lib/Roundcube/rcube_sieve_vacation.php 2026-02-08 10:25:02.000000000 +0100 @@ -150,6 +150,14 @@ } } + // According to RFC5260, currentdate target can be a string-list, + // but here we support only a single value (#10074) + foreach ($rule['tests'] as $i => $r) { + if ($r['test'] == 'currentdate' && is_array($r['arg'])) { + $rule['tests'][$i]['arg'] = array_first($r['arg']); + } + } + $this->vacation = array_merge($rule['actions'][0], [ 'idx' => $idx, 'disabled' => $rule['disabled'] || !$active, diff -Nru roundcube-1.6.12+dfsg/program/lib/Roundcube/rcube_utils.php roundcube-1.6.13+dfsg/program/lib/Roundcube/rcube_utils.php --- roundcube-1.6.12+dfsg/program/lib/Roundcube/rcube_utils.php 2025-12-14 09:10:51.000000000 +0100 +++ roundcube-1.6.13+dfsg/program/lib/Roundcube/rcube_utils.php 2026-02-08 10:25:02.000000000 +0100 @@ -432,7 +432,7 @@ */ public static function mod_css_styles($source, $container_id, $allow_remote = false, $prefix = '') { - $source = self::xss_entity_decode($source); + $source = self::xss_entity_decode($source); // No @import allowed // TODO: We should just remove it, not invalidate the whole content @@ -445,6 +445,9 @@ return '/* invalid! */'; } + // remove html and css comments + $source = preg_replace('/(^\s*<\!--)|(-->\s*$)/m', '', $source); + // To prevent from a double-escaping tricks we consider a script with // any escape sequences (after de-escaping them above) an evil script. // This probably catches many valid scripts, but we\'re on the safe side. @@ -452,8 +455,12 @@ return '/* evil! */'; } - // remove html comments - $source = preg_replace('/(^\s*<\!--)|(-->\s*$)/m', '', $source); + // If after removing comments there are still comments it's most likely a hack + // Note: In <=1.6 comments are being removed by xss_entity_decode() above + // $source = self::remove_css_comments($source); + if (strpos($source, '/*') !== false || strpos($source, '<!--') !== false) { + return '/* evil! */'; + } $url_callback = static function ($url) use ($allow_remote) { if (strpos($url, 'data:image') === 0) { @@ -468,8 +475,14 @@ $replacements = new rcube_string_replacer(); // cut out all contents between { and } - while (($pos = strpos($source, '{', $last_pos)) && ($pos2 = strpos($source, '}', $pos))) { - $nested = strpos($source, '{', $pos+1); + while (($pos = strpos($source, '{', $last_pos)) && ($pos2 = strpos($source, '}', $pos) ?: (strlen($source) - 1))) { + // In case there was no closing brace add one + if ($source[$pos2] != '}') { + $pos2++; + $source .= '}'; + } + + $nested = strpos($source, '{', $pos + 1); if ($nested && $nested < $pos2) { // when dealing with nested blocks (e.g. @media), take the inner one $pos = $nested; } @@ -559,7 +572,7 @@ $value .= ' url(' . $url . ')'; } } - } elseif (preg_match('/;.*/', $val)) { + } elseif (preg_match('/;.+/', $val)) { // Invalid or evil content, ignore continue; } else { @@ -595,19 +608,8 @@ */ public static function parse_css_block($style) { - $pos = 0; - - // first remove comments - while (($pos = strpos($style, '/*', $pos)) !== false) { - $end = strpos($style, '*/', $pos+2); - - if ($end === false) { - $style = substr($style, 0, $pos); - } - else { - $style = substr_replace($style, '', $pos, $end - $pos + 2); - } - } + // Remove comments + $style = self::remove_css_comments($style); // Replace new lines with spaces $style = preg_replace('/[\r\n]+/', ' ', $style); @@ -660,6 +662,30 @@ } /** + * Remove CSS comments from styles. + * + * @param string $style CSS style + * + * @return string CSS style + */ + public static function remove_css_comments($style) + { + $pos = 0; + + while (($pos = strpos($style, '/*', $pos)) !== false) { + $end = strpos($style, '*/', $pos + 2); + + if ($end === false) { + $style = substr($style, 0, $pos); + } else { + $style = substr_replace($style, '', $pos, $end - $pos + 2); + } + } + + return $style; + } + + /** * Explode css style value * * @param string $style CSS style diff -Nru roundcube-1.6.12+dfsg/program/lib/Roundcube/rcube_washtml.php roundcube-1.6.13+dfsg/program/lib/Roundcube/rcube_washtml.php --- roundcube-1.6.12+dfsg/program/lib/Roundcube/rcube_washtml.php 2025-12-14 09:10:51.000000000 +0100 +++ roundcube-1.6.13+dfsg/program/lib/Roundcube/rcube_washtml.php 2026-02-08 10:25:02.000000000 +0100 @@ -482,8 +482,7 @@ || $attr == 'color-profile' // SVG || ($attr == 'poster' && $tag == 'video') || ($attr == 'src' && preg_match('/^(img|image|source|input|video|audio)$/i', $tag)) - || ($tag == 'use' && $attr == 'href') // SVG - || ($tag == 'image' && $attr == 'href'); // SVG + || ($attr == 'href' && preg_match('/^(feimage|image|use)$/i', $tag)); // SVG } /** diff -Nru roundcube-1.6.12+dfsg/public_html/plugins/managesieve/Changelog roundcube-1.6.13+dfsg/public_html/plugins/managesieve/Changelog --- roundcube-1.6.12+dfsg/public_html/plugins/managesieve/Changelog 2025-12-14 09:10:51.000000000 +0100 +++ roundcube-1.6.13+dfsg/public_html/plugins/managesieve/Changelog 2026-02-08 10:25:02.000000000 +0100 @@ -1,3 +1,4 @@ +- Fix handling of string-list format values for date tests in Out of Office (#10075) - Fix invalid line break characters in multi-line text in Sieve scripts (#9543) - Fix javascript error when relational or spamtest extension is not enabled (#9139) - Removed managesieve_usetls option (in favor of the scheme prefix in managesieve_host) diff -Nru roundcube-1.6.12+dfsg/public_html/plugins/managesieve/lib/Roundcube/rcube_sieve_vacation.php roundcube-1.6.13+dfsg/public_html/plugins/managesieve/lib/Roundcube/rcube_sieve_vacation.php --- roundcube-1.6.12+dfsg/public_html/plugins/managesieve/lib/Roundcube/rcube_sieve_vacation.php 2025-12-14 09:10:51.000000000 +0100 +++ roundcube-1.6.13+dfsg/public_html/plugins/managesieve/lib/Roundcube/rcube_sieve_vacation.php 2026-02-08 10:25:02.000000000 +0100 @@ -150,6 +150,14 @@ } } + // According to RFC5260, currentdate target can be a string-list, + // but here we support only a single value (#10074) + foreach ($rule['tests'] as $i => $r) { + if ($r['test'] == 'currentdate' && is_array($r['arg'])) { + $rule['tests'][$i]['arg'] = array_first($r['arg']); + } + } + $this->vacation = array_merge($rule['actions'][0], [ 'idx' => $idx, 'disabled' => $rule['disabled'] || !$active, diff -Nru roundcube-1.6.12+dfsg/tests/Framework/Utils.php roundcube-1.6.13+dfsg/tests/Framework/Utils.php --- roundcube-1.6.12+dfsg/tests/Framework/Utils.php 2025-12-14 09:10:51.000000000 +0100 +++ roundcube-1.6.13+dfsg/tests/Framework/Utils.php 2026-02-08 10:25:02.000000000 +0100 @@ -276,6 +276,10 @@ $mod = rcube_utils::mod_css_styles(".test { position\n: fixed; top: 0; }", 'rcmbody'); $this->assertEquals("#rcmbody .test { position: absolute; top: 0; }", $mod, "Replace position:fixed with position:absolute (5)"); + // missing closing brace + $mod = \rcube_utils::mod_css_styles('.test { position: fixed; top: 0;', 'rcmbody'); + $this->assertSame('#rcmbody .test { position: absolute; top: 0; }', $mod, 'Replace position:fixed with position:absolute (6)'); + // allow data URIs with images (#5580) $mod = rcube_utils::mod_css_styles("body { background-image: url(data:image/png;base64,123); }", 'rcmbody'); $this->assertStringContainsString("#rcmbody { background-image: url(data:image/png;base64,123);", $mod, "Data URIs in url() allowed [1]"); @@ -300,9 +304,15 @@ $mod = rcube_utils::mod_css_styles($style, 'rcmbody', true); $this->assertSame("#rcmbody { color: red; }", $mod); - $style = "body { background:url(alert('URL!')); }"; - $mod = rcube_utils::mod_css_styles($style, 'rcmbody', true); - $this->assertSame("#rcmbody {}", $mod); + $style = 'body { background:url(alert('URL!')); }'; + $mod = \rcube_utils::mod_css_styles($style, 'rcmbody', true); + $this->assertSame('#rcmbody {}', $mod); + + // CSS comments and nesting + $mod = \rcube_utils::mod_css_styles('/* b { content: "*/* {background-color: silver;}', 'rcmbody', true); + $this->assertSame('#rcmbody * { background-color: silver; }', $mod); + $mod = \rcube_utils::mod_css_styles('//* test */* {background-color: silver;}', 'rcmbody', true); + $this->assertSame('/* evil! */', $mod); } /** diff -Nru roundcube-1.6.12+dfsg/tests/Framework/Washtml.php roundcube-1.6.13+dfsg/tests/Framework/Washtml.php --- roundcube-1.6.12+dfsg/tests/Framework/Washtml.php 2025-12-14 09:10:51.000000000 +0100 +++ roundcube-1.6.13+dfsg/tests/Framework/Washtml.php 2026-02-08 10:25:02.000000000 +0100 @@ -492,6 +492,14 @@ '<html><svg><animate attributeName="href " values="javascript:alert(\'XSS\')" href="#link" /></animate></svg></html>', '<svg><!-- animate blocked --></svg>', ], + [ + '<html><svg><defs><filter><feImage href="http://external.site"/></filter></defs></html>', + '<svg><defs><filter><feImage x-washed="href"></feImage></filter></defs></svg>', + ], + [ + '<html><svg><defs><filter><feImage xlink:href="http://external.site"/></filter></defs></html>', + '<svg><defs><filter><feImage x-washed="xlink:href"></feImage></filter></defs></svg>', + ], ]; }
diffstat for roundcube-1.6.5+dfsg roundcube-1.6.5+dfsg changelog | 9 + patches/CVE-2025-68460.patch | 64 ------------- patches/CVE-2025-68460/01-08de250fb.patch | 64 +++++++++++++ patches/CVE-2025-68460/02-a7349a4e2.patch | 25 +++++ patches/CVE-2026-25916/01-036e851b6.patch | 48 +++++++++ patches/CVE-2026-25916/02-2b5625f1d.patch | 31 ++++++ patches/CVE-2026-26079/01-1f4c3a5af.patch | 145 ++++++++++++++++++++++++++++++ patches/CVE-2026-26079/02-2b5625f1d.patch | 25 +++++ patches/CVE-2026-26079/03-53d75d5df.patch | 42 ++++++++ patches/series | 8 + 10 files changed, 396 insertions(+), 65 deletions(-) diff -Nru roundcube-1.6.5+dfsg/debian/changelog roundcube-1.6.5+dfsg/debian/changelog --- roundcube-1.6.5+dfsg/debian/changelog 2025-12-16 09:10:17.000000000 +0100 +++ roundcube-1.6.5+dfsg/debian/changelog 2026-02-11 12:05:21.000000000 +0100 @@ -1,3 +1,12 @@ +roundcube (1.6.5+dfsg-1+deb12u7) bookworm; urgency=medium + + * Cherry pick upstream security fixes from v1.6.13 (closes: #1127447): + + Fix CVE-2026-26079: CSS injection vulnerability. + + Fix CVE-2026-25916: Remote image blocking bypass via SVG content. + + Cherry-pick improvement change for CVE-2025-68460. + + -- Guilhem Moulin <[email protected]> Wed, 11 Feb 2026 12:05:21 +0100 + roundcube (1.6.5+dfsg-1+deb12u6) bookworm-security; urgency=high * Cherry pick upstream security fixes from v1.6.12 (closes: #1122899): diff -Nru roundcube-1.6.5+dfsg/debian/patches/CVE-2025-68460/01-08de250fb.patch roundcube-1.6.5+dfsg/debian/patches/CVE-2025-68460/01-08de250fb.patch --- roundcube-1.6.5+dfsg/debian/patches/CVE-2025-68460/01-08de250fb.patch 1970-01-01 01:00:00.000000000 +0100 +++ roundcube-1.6.5+dfsg/debian/patches/CVE-2025-68460/01-08de250fb.patch 2026-02-11 12:05:21.000000000 +0100 @@ -0,0 +1,64 @@ +From: Aleksander Machniak <[email protected]> +Date: Sun, 14 Dec 2025 09:02:25 +0100 +Subject: Fix Information Disclosure vulnerability in the HTML style sanitizer + +reported by somerandomdev + +Origin: https://github.com/roundcube/roundcubemail/commit/08de250fba731b634bed188bbe18d2f6ef3c7571 +Bug: https://roundcube.net/news/2025/12/13/security-updates-1.6.12-and-1.5.12 +Bug-Debian: https://bugs.debian.org/1122899 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2025-68460 +--- + program/lib/Roundcube/rcube_utils.php | 3 +++ + tests/Framework/Utils.php | 4 ++-- + tests/Framework/Washtml.php | 7 +++++++ + 3 files changed, 12 insertions(+), 2 deletions(-) + +diff --git a/program/lib/Roundcube/rcube_utils.php b/program/lib/Roundcube/rcube_utils.php +index b5f8606..1110905 100644 +--- a/program/lib/Roundcube/rcube_utils.php ++++ b/program/lib/Roundcube/rcube_utils.php +@@ -559,6 +559,9 @@ class rcube_utils + $value .= ' url(' . $url . ')'; + } + } ++ } elseif (preg_match('/;.*/', $val)) { ++ // Invalid or evil content, ignore ++ continue; + } else { + // whitelist ? + $value .= ' ' . $val; +diff --git a/tests/Framework/Utils.php b/tests/Framework/Utils.php +index 019895b..4b43758 100644 +--- a/tests/Framework/Utils.php ++++ b/tests/Framework/Utils.php +@@ -291,9 +291,9 @@ class Framework_Utils extends PHPUnit\Framework\TestCase + $mod = rcube_utils::mod_css_styles($style, 'rcmbody', true); + $this->assertSame("#rcmbody { content: ''; color: red; }", $mod); + +- $style = "body { content: '< page: ;/style>< page: ;img src onerror=\"alert(\'hello\');\">'; color: red; }"; ++ $style = "body { content: '< page: ;/style>< page: ;img src onerror=\"alert(\\'hello\\');\">'; color: red; }"; + $mod = rcube_utils::mod_css_styles($style, 'rcmbody', true); +- $this->assertSame("#rcmbody { content: '< page: ;/style>< page: ;img src onerror=\"alert('hello');\">'; color: red; }", $mod); ++ $this->assertSame("#rcmbody { color: red; }", $mod); + + // Removing page: property + $style = "body { page: test; color: red }"; +diff --git a/tests/Framework/Washtml.php b/tests/Framework/Washtml.php +index ace4716..0b9e1e9 100644 +--- a/tests/Framework/Washtml.php ++++ b/tests/Framework/Washtml.php +@@ -312,6 +312,13 @@ class Framework_Washtml extends PHPUnit\Framework\TestCase + $washed = $washer->wash($html); + + $this->assertTrue(strpos($washed, $exp) !== false, "Style quotes XSS issue (#1490227)"); ++ ++ $html = '<div style=\'content: "\0026quot;; background: url(//http.cat/418); content:""; width: 100%; height: 100%;\'>test</div>'; ++ ++ $washer = new \rcube_washtml(); ++ $washed = $washer->wash($html); ++ ++ $this->assertTrue(strpos($washed, '<div x-washed="style">test</div>') !== false); + } + + /** diff -Nru roundcube-1.6.5+dfsg/debian/patches/CVE-2025-68460/02-a7349a4e2.patch roundcube-1.6.5+dfsg/debian/patches/CVE-2025-68460/02-a7349a4e2.patch --- roundcube-1.6.5+dfsg/debian/patches/CVE-2025-68460/02-a7349a4e2.patch 1970-01-01 01:00:00.000000000 +0100 +++ roundcube-1.6.5+dfsg/debian/patches/CVE-2025-68460/02-a7349a4e2.patch 2026-02-11 12:05:21.000000000 +0100 @@ -0,0 +1,25 @@ +From: Aleksander Machniak <[email protected]> +Date: Mon, 15 Dec 2025 11:36:05 +0100 +Subject: Fix the regexp so it will produce less false-positives + +Origin: https://github.com/roundcube/roundcubemail/commit/a7349a4e21d27e0a3786139e4c879f236cafe4b1 +Bug: https://roundcube.net/news/2025/12/13/security-updates-1.6.12-and-1.5.12 +Bug-Debian: https://bugs.debian.org/1122899 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2025-68460 +--- + program/lib/Roundcube/rcube_utils.php | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/program/lib/Roundcube/rcube_utils.php b/program/lib/Roundcube/rcube_utils.php +index 1110905..13f1915 100644 +--- a/program/lib/Roundcube/rcube_utils.php ++++ b/program/lib/Roundcube/rcube_utils.php +@@ -559,7 +559,7 @@ class rcube_utils + $value .= ' url(' . $url . ')'; + } + } +- } elseif (preg_match('/;.*/', $val)) { ++ } elseif (preg_match('/;.+/', $val)) { + // Invalid or evil content, ignore + continue; + } else { diff -Nru roundcube-1.6.5+dfsg/debian/patches/CVE-2025-68460.patch roundcube-1.6.5+dfsg/debian/patches/CVE-2025-68460.patch --- roundcube-1.6.5+dfsg/debian/patches/CVE-2025-68460.patch 2025-12-16 09:10:17.000000000 +0100 +++ roundcube-1.6.5+dfsg/debian/patches/CVE-2025-68460.patch 1970-01-01 01:00:00.000000000 +0100 @@ -1,64 +0,0 @@ -From: Aleksander Machniak <[email protected]> -Date: Sun, 14 Dec 2025 09:02:25 +0100 -Subject: Fix Information Disclosure vulnerability in the HTML style sanitizer - -reported by somerandomdev - -Origin: https://github.com/roundcube/roundcubemail/commit/08de250fba731b634bed188bbe18d2f6ef3c7571 -Bug: https://roundcube.net/news/2025/12/13/security-updates-1.6.12-and-1.5.12 -Bug-Debian: https://bugs.debian.org/1122899 -Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2025-68460 ---- - program/lib/Roundcube/rcube_utils.php | 3 +++ - tests/Framework/Utils.php | 4 ++-- - tests/Framework/Washtml.php | 7 +++++++ - 3 files changed, 12 insertions(+), 2 deletions(-) - -diff --git a/program/lib/Roundcube/rcube_utils.php b/program/lib/Roundcube/rcube_utils.php -index b5f8606..1110905 100644 ---- a/program/lib/Roundcube/rcube_utils.php -+++ b/program/lib/Roundcube/rcube_utils.php -@@ -559,6 +559,9 @@ class rcube_utils - $value .= ' url(' . $url . ')'; - } - } -+ } elseif (preg_match('/;.*/', $val)) { -+ // Invalid or evil content, ignore -+ continue; - } else { - // whitelist ? - $value .= ' ' . $val; -diff --git a/tests/Framework/Utils.php b/tests/Framework/Utils.php -index 019895b..4b43758 100644 ---- a/tests/Framework/Utils.php -+++ b/tests/Framework/Utils.php -@@ -291,9 +291,9 @@ class Framework_Utils extends PHPUnit\Framework\TestCase - $mod = rcube_utils::mod_css_styles($style, 'rcmbody', true); - $this->assertSame("#rcmbody { content: ''; color: red; }", $mod); - -- $style = "body { content: '< page: ;/style>< page: ;img src onerror=\"alert(\'hello\');\">'; color: red; }"; -+ $style = "body { content: '< page: ;/style>< page: ;img src onerror=\"alert(\\'hello\\');\">'; color: red; }"; - $mod = rcube_utils::mod_css_styles($style, 'rcmbody', true); -- $this->assertSame("#rcmbody { content: '< page: ;/style>< page: ;img src onerror=\"alert('hello');\">'; color: red; }", $mod); -+ $this->assertSame("#rcmbody { color: red; }", $mod); - - // Removing page: property - $style = "body { page: test; color: red }"; -diff --git a/tests/Framework/Washtml.php b/tests/Framework/Washtml.php -index ace4716..0b9e1e9 100644 ---- a/tests/Framework/Washtml.php -+++ b/tests/Framework/Washtml.php -@@ -312,6 +312,13 @@ class Framework_Washtml extends PHPUnit\Framework\TestCase - $washed = $washer->wash($html); - - $this->assertTrue(strpos($washed, $exp) !== false, "Style quotes XSS issue (#1490227)"); -+ -+ $html = '<div style=\'content: "\0026quot;; background: url(//http.cat/418); content:""; width: 100%; height: 100%;\'>test</div>'; -+ -+ $washer = new \rcube_washtml(); -+ $washed = $washer->wash($html); -+ -+ $this->assertTrue(strpos($washed, '<div x-washed="style">test</div>') !== false); - } - - /** diff -Nru roundcube-1.6.5+dfsg/debian/patches/CVE-2026-25916/01-036e851b6.patch roundcube-1.6.5+dfsg/debian/patches/CVE-2026-25916/01-036e851b6.patch --- roundcube-1.6.5+dfsg/debian/patches/CVE-2026-25916/01-036e851b6.patch 1970-01-01 01:00:00.000000000 +0100 +++ roundcube-1.6.5+dfsg/debian/patches/CVE-2026-25916/01-036e851b6.patch 2026-02-11 12:05:21.000000000 +0100 @@ -0,0 +1,48 @@ +From: Aleksander Machniak <[email protected]> +Date: Sun, 8 Feb 2026 09:21:34 +0100 +Subject: Fix remote image blocking bypass via SVG content reported by + nullcathedral + +Origin: https://github.com/roundcube/roundcubemail/commit/036e851b683333205813f70acda2dc047b4891c8 +Bug: https://roundcube.net/news/2026/02/08/security-updates-1.6.13-and-1.5.13 +Bug: https://nullcathedral.com/posts/2026-02-08-roundcube-svg-feimage-remote-image-bypass/ +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2026-25916 +Bug-Debian: https://bugs.debian.org/1127447 +--- + program/lib/Roundcube/rcube_washtml.php | 3 +-- + tests/Framework/Washtml.php | 8 ++++++++ + 2 files changed, 9 insertions(+), 2 deletions(-) + +diff --git a/program/lib/Roundcube/rcube_washtml.php b/program/lib/Roundcube/rcube_washtml.php +index 85972f0..8721fe7 100644 +--- a/program/lib/Roundcube/rcube_washtml.php ++++ b/program/lib/Roundcube/rcube_washtml.php +@@ -482,8 +482,7 @@ class rcube_washtml + || $attr == 'color-profile' // SVG + || ($attr == 'poster' && $tag == 'video') + || ($attr == 'src' && preg_match('/^(img|image|source|input|video|audio)$/i', $tag)) +- || ($tag == 'use' && $attr == 'href') // SVG +- || ($tag == 'image' && $attr == 'href'); // SVG ++ || ($attr == 'href' && preg_match('/^(feimage|image|use)$/i', $tag)); // SVG + } + + /** +diff --git a/tests/Framework/Washtml.php b/tests/Framework/Washtml.php +index 0b9e1e9..be404af 100644 +--- a/tests/Framework/Washtml.php ++++ b/tests/Framework/Washtml.php +@@ -492,6 +492,14 @@ class Framework_Washtml extends PHPUnit\Framework\TestCase + '<html><svg><animate attributeName="href " values="javascript:alert(\'XSS\')" href="#link" /></animate></svg></html>', + '<svg><!-- animate blocked --></svg>', + ], ++ [ ++ '<html><svg><defs><filter><feImage href="http://external.site"/></filter></defs></html>', ++ '<svg><defs><filter><feimage x-washed="href"></feimage></filter></defs></svg>', ++ ], ++ [ ++ '<html><svg><defs><filter><feImage xlink:href="http://external.site"/></filter></defs></html>', ++ '<svg><defs><filter><feimage x-washed="xlink:href"></feimage></filter></defs></svg>', ++ ], + ]; + } + diff -Nru roundcube-1.6.5+dfsg/debian/patches/CVE-2026-25916/02-2b5625f1d.patch roundcube-1.6.5+dfsg/debian/patches/CVE-2026-25916/02-2b5625f1d.patch --- roundcube-1.6.5+dfsg/debian/patches/CVE-2026-25916/02-2b5625f1d.patch 1970-01-01 01:00:00.000000000 +0100 +++ roundcube-1.6.5+dfsg/debian/patches/CVE-2026-25916/02-2b5625f1d.patch 2026-02-11 12:05:21.000000000 +0100 @@ -0,0 +1,31 @@ +From: Aleksander Machniak <[email protected]> +Date: Sun, 8 Feb 2026 10:13:39 +0100 +Subject: Fix regression + +Origin: https://github.com/roundcube/roundcubemail/commit/2b5625f1d2ef7e050fd1ae481b2a52dc35466447#diff-458653d23200a96c6f32ce2835e5d77128018494e800b9ead6d9542b778ff88e +Bug: https://roundcube.net/news/2026/02/08/security-updates-1.6.13-and-1.5.13 +Bug: https://nullcathedral.com/posts/2026-02-08-roundcube-svg-feimage-remote-image-bypass/ +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2026-25916 +Bug-Debian: https://bugs.debian.org/1127447 +--- + tests/Framework/Washtml.php | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tests/Framework/Washtml.php b/tests/Framework/Washtml.php +index be404af..ef324f8 100644 +--- a/tests/Framework/Washtml.php ++++ b/tests/Framework/Washtml.php +@@ -494,11 +494,11 @@ class Framework_Washtml extends PHPUnit\Framework\TestCase + ], + [ + '<html><svg><defs><filter><feImage href="http://external.site"/></filter></defs></html>', +- '<svg><defs><filter><feimage x-washed="href"></feimage></filter></defs></svg>', ++ '<svg><defs><filter><feImage x-washed="href"></feImage></filter></defs></svg>', + ], + [ + '<html><svg><defs><filter><feImage xlink:href="http://external.site"/></filter></defs></html>', +- '<svg><defs><filter><feimage x-washed="xlink:href"></feimage></filter></defs></svg>', ++ '<svg><defs><filter><feImage x-washed="xlink:href"></feImage></filter></defs></svg>', + ], + ]; + } diff -Nru roundcube-1.6.5+dfsg/debian/patches/CVE-2026-26079/01-1f4c3a5af.patch roundcube-1.6.5+dfsg/debian/patches/CVE-2026-26079/01-1f4c3a5af.patch --- roundcube-1.6.5+dfsg/debian/patches/CVE-2026-26079/01-1f4c3a5af.patch 1970-01-01 01:00:00.000000000 +0100 +++ roundcube-1.6.5+dfsg/debian/patches/CVE-2026-26079/01-1f4c3a5af.patch 2026-02-11 12:05:21.000000000 +0100 @@ -0,0 +1,145 @@ +From: Aleksander Machniak <[email protected]> +Date: Sun, 8 Feb 2026 09:24:29 +0100 +Subject: Fix CSS injection vulnerability reported by CERT Polska + +Origin: https://github.com/roundcube/roundcubemail/commit/1f4c3a5af5033747f9685a8a395dbd8228d19816 +Bug: https://roundcube.net/news/2026/02/08/security-updates-1.6.13-and-1.5.13 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2026-26079 +Bug-Debian: https://bugs.debian.org/1127447 +--- + program/lib/Roundcube/rcube_utils.php | 59 +++++++++++++++++++++++++---------- + tests/Framework/Utils.php | 16 ++++++++-- + 2 files changed, 55 insertions(+), 20 deletions(-) + +diff --git a/program/lib/Roundcube/rcube_utils.php b/program/lib/Roundcube/rcube_utils.php +index 13f1915..51f5bb7 100644 +--- a/program/lib/Roundcube/rcube_utils.php ++++ b/program/lib/Roundcube/rcube_utils.php +@@ -445,6 +445,10 @@ class rcube_utils + return '/* invalid! */'; + } + ++ // remove html and css comments ++ $source = preg_replace('/(^\s*<\!--)|(-->\s*$)/m', '', $source); ++ $source = self::remove_css_comments($source); ++ + // To prevent from a double-escaping tricks we consider a script with + // any escape sequences (after de-escaping them above) an evil script. + // This probably catches many valid scripts, but we\'re on the safe side. +@@ -452,8 +456,10 @@ class rcube_utils + return '/* evil! */'; + } + +- // remove html comments +- $source = preg_replace('/(^\s*<\!--)|(-->\s*$)/m', '', $source); ++ // If after removing comments there are still comments it's most likely a hack ++ if (strpos('/*', $source) !== false || strpos('<!--', $source) !== false) { ++ return '/* evil! */'; ++ } + + $url_callback = static function ($url) use ($allow_remote) { + if (strpos($url, 'data:image') === 0) { +@@ -468,8 +474,14 @@ class rcube_utils + $replacements = new rcube_string_replacer(); + + // cut out all contents between { and } +- while (($pos = strpos($source, '{', $last_pos)) && ($pos2 = strpos($source, '}', $pos))) { +- $nested = strpos($source, '{', $pos+1); ++ while (($pos = strpos($source, '{', $last_pos)) && ($pos2 = strpos($source, '}', $pos) ?: (strlen($source) - 1))) { ++ // In case there was no closing brace add one ++ if ($source[$pos2] != '}') { ++ $pos2++; ++ $source .= '}'; ++ } ++ ++ $nested = strpos($source, '{', $pos + 1); + if ($nested && $nested < $pos2) { // when dealing with nested blocks (e.g. @media), take the inner one + $pos = $nested; + } +@@ -595,19 +607,8 @@ class rcube_utils + */ + public static function parse_css_block($style) + { +- $pos = 0; +- +- // first remove comments +- while (($pos = strpos($style, '/*', $pos)) !== false) { +- $end = strpos($style, '*/', $pos+2); +- +- if ($end === false) { +- $style = substr($style, 0, $pos); +- } +- else { +- $style = substr_replace($style, '', $pos, $end - $pos + 2); +- } +- } ++ // Remove comments ++ $style = self::remove_css_comments($style); + + // Replace new lines with spaces + $style = preg_replace('/[\r\n]+/', ' ', $style); +@@ -657,6 +658,30 @@ class rcube_utils + return $result; + } + ++ /** ++ * Remove CSS comments from styles. ++ * ++ * @param string $style CSS style ++ * ++ * @return string CSS style ++ */ ++ public static function remove_css_comments($style) ++ { ++ $pos = 0; ++ ++ while (($pos = strpos($style, '/*', $pos)) !== false) { ++ $end = strpos($style, '*/', $pos + 2); ++ ++ if ($end === false) { ++ $style = substr($style, 0, $pos); ++ } else { ++ $style = substr_replace($style, '', $pos, $end - $pos + 2); ++ } ++ } ++ ++ return $style; ++ } ++ + /** + * Explode css style value + * +diff --git a/tests/Framework/Utils.php b/tests/Framework/Utils.php +index 4b43758..c0e9aea 100644 +--- a/tests/Framework/Utils.php ++++ b/tests/Framework/Utils.php +@@ -276,6 +276,10 @@ class Framework_Utils extends PHPUnit\Framework\TestCase + $mod = rcube_utils::mod_css_styles(".test { position\n: fixed; top: 0; }", 'rcmbody'); + $this->assertEquals("#rcmbody .test { position: absolute; top: 0; }", $mod, "Replace position:fixed with position:absolute (5)"); + ++ // missing closing brace ++ $mod = \rcube_utils::mod_css_styles('.test { position: fixed; top: 0;', 'rcmbody'); ++ $this->assertSame('#rcmbody .test { position: absolute; top: 0; }', $mod, 'Replace position:fixed with position:absolute (6)'); ++ + // allow data URIs with images (#5580) + $mod = rcube_utils::mod_css_styles("body { background-image: url(data:image/png;base64,123); }", 'rcmbody'); + $this->assertStringContainsString("#rcmbody { background-image: url(data:image/png;base64,123);", $mod, "Data URIs in url() allowed [1]"); +@@ -300,9 +304,15 @@ class Framework_Utils extends PHPUnit\Framework\TestCase + $mod = rcube_utils::mod_css_styles($style, 'rcmbody', true); + $this->assertSame("#rcmbody { color: red; }", $mod); + +- $style = "body { background:url(alert('URL!')); }"; +- $mod = rcube_utils::mod_css_styles($style, 'rcmbody', true); +- $this->assertSame("#rcmbody {}", $mod); ++ $style = 'body { background:url(alert('URL!')); }'; ++ $mod = \rcube_utils::mod_css_styles($style, 'rcmbody', true); ++ $this->assertSame('#rcmbody {}', $mod); ++ ++ // CSS comments and nesting ++ $mod = \rcube_utils::mod_css_styles('/* b { content: "*/* {background-color: silver;}', 'rcmbody', true); ++ $this->assertSame('#rcmbody * { background-color: silver; }', $mod); ++ $mod = \rcube_utils::mod_css_styles('//* test */* {background-color: silver;}', 'rcmbody', true); ++ $this->assertSame('/* evil! */', $mod); + } + + /** diff -Nru roundcube-1.6.5+dfsg/debian/patches/CVE-2026-26079/02-2b5625f1d.patch roundcube-1.6.5+dfsg/debian/patches/CVE-2026-26079/02-2b5625f1d.patch --- roundcube-1.6.5+dfsg/debian/patches/CVE-2026-26079/02-2b5625f1d.patch 1970-01-01 01:00:00.000000000 +0100 +++ roundcube-1.6.5+dfsg/debian/patches/CVE-2026-26079/02-2b5625f1d.patch 2026-02-11 12:05:21.000000000 +0100 @@ -0,0 +1,25 @@ +From: Aleksander Machniak <[email protected]> +Date: Sun, 8 Feb 2026 10:13:39 +0100 +Subject: Fix regression + +Origin: https://github.com/roundcube/roundcubemail/commit/2b5625f1d2ef7e050fd1ae481b2a52dc35466447#diff-a3f09795bbbad6183803c522e358c5aa6a468c84ab3bcc9c5de60f0ab70fa101 +Bug: https://roundcube.net/news/2026/02/08/security-updates-1.6.13-and-1.5.13 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2026-26079 +Bug-Debian: https://bugs.debian.org/1127447 +--- + program/lib/Roundcube/rcube_utils.php | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/program/lib/Roundcube/rcube_utils.php b/program/lib/Roundcube/rcube_utils.php +index 51f5bb7..a29a87d 100644 +--- a/program/lib/Roundcube/rcube_utils.php ++++ b/program/lib/Roundcube/rcube_utils.php +@@ -457,7 +457,7 @@ class rcube_utils + } + + // If after removing comments there are still comments it's most likely a hack +- if (strpos('/*', $source) !== false || strpos('<!--', $source) !== false) { ++ if (strpos($source, '/*') !== false || strpos($source, '<!--') !== false) { + return '/* evil! */'; + } + diff -Nru roundcube-1.6.5+dfsg/debian/patches/CVE-2026-26079/03-53d75d5df.patch roundcube-1.6.5+dfsg/debian/patches/CVE-2026-26079/03-53d75d5df.patch --- roundcube-1.6.5+dfsg/debian/patches/CVE-2026-26079/03-53d75d5df.patch 1970-01-01 01:00:00.000000000 +0100 +++ roundcube-1.6.5+dfsg/debian/patches/CVE-2026-26079/03-53d75d5df.patch 2026-02-11 12:05:21.000000000 +0100 @@ -0,0 +1,42 @@ +From: Aleksander Machniak <[email protected]> +Date: Sun, 8 Feb 2026 10:25:02 +0100 +Subject: Fix regression + +Origin: https://github.com/roundcube/roundcubemail/commit/53d75d5dfebef235a344d476b900c20c12d52b01 +Bug: https://roundcube.net/news/2026/02/08/security-updates-1.6.13-and-1.5.13 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2026-26079 +Bug-Debian: https://bugs.debian.org/1127447 +--- + program/lib/Roundcube/rcube_utils.php | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/program/lib/Roundcube/rcube_utils.php b/program/lib/Roundcube/rcube_utils.php +index a29a87d..d847461 100644 +--- a/program/lib/Roundcube/rcube_utils.php ++++ b/program/lib/Roundcube/rcube_utils.php +@@ -432,7 +432,7 @@ class rcube_utils + */ + public static function mod_css_styles($source, $container_id, $allow_remote = false, $prefix = '') + { +- $source = self::xss_entity_decode($source); ++ $source = self::xss_entity_decode($source); + + // No @import allowed + // TODO: We should just remove it, not invalidate the whole content +@@ -447,7 +447,6 @@ class rcube_utils + + // remove html and css comments + $source = preg_replace('/(^\s*<\!--)|(-->\s*$)/m', '', $source); +- $source = self::remove_css_comments($source); + + // To prevent from a double-escaping tricks we consider a script with + // any escape sequences (after de-escaping them above) an evil script. +@@ -457,6 +456,8 @@ class rcube_utils + } + + // If after removing comments there are still comments it's most likely a hack ++ // Note: In <=1.6 comments are being removed by xss_entity_decode() above ++ // $source = self::remove_css_comments($source); + if (strpos($source, '/*') !== false || strpos($source, '<!--') !== false) { + return '/* evil! */'; + } 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 2025-12-16 09:10:17.000000000 +0100 +++ roundcube-1.6.5+dfsg/debian/patches/series 2026-02-11 12:05:21.000000000 +0100 @@ -29,4 +29,10 @@ Fix-regression-where-HTML-messages-were-displayed-unstyle.patch CVE-2025-49113.patch CVE-2025-68461.patch -CVE-2025-68460.patch +CVE-2025-68460/01-08de250fb.patch +CVE-2025-68460/02-a7349a4e2.patch +CVE-2026-25916/01-036e851b6.patch +CVE-2026-25916/02-2b5625f1d.patch +CVE-2026-26079/01-1f4c3a5af.patch +CVE-2026-26079/02-2b5625f1d.patch +CVE-2026-26079/03-53d75d5df.patch
signature.asc
Description: PGP signature

