CVE-2026-48843
Description
Roundcube Webmail 1.6.x between 1.6.14 and 1.6.16,and 1.7.x before 1.7.1 has Insufficient Cascading Style Sheets (CSS) sanitization in HTML e-mail messages may lead to SSRF or Information Disclosure, e.g., if stylesheet links point to local network hosts. The issue stems from an insufficient fix for CVE-2026-35540.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Roundcube Webmail versions 1.6.14 to 1.6.16 and 1.7.x before 1.7.1 are vulnerable to SSRF or information disclosure via insufficient CSS sanitization in HTML email.
Vulnerability
Roundcube Webmail versions 1.6.14 through 1.6.16 (LTS branch) and 1.7.x prior to 1.7.1 [1][2] contain a server-side request forgery (SSRF) and information disclosure vulnerability due to insufficient cascading style sheets (CSS) sanitization. An email message with crafted stylesheet links can point to local network hosts, bypassing local URL address checks. The issue stems from an incomplete fix for CVE-2026-35540, specifically in the is_local_url() function where the IP address parsing used Factory::parseAddressString without flags to handle non-decimal or non-standard IPv4 representations, and missed hostnames like 0.0.0.0 or loops via nip.io domains [1][2].
Exploitation
An attacker sends an HTML email to a Roundcube user containing a CSS @import url() or url() that references a crafted URL pointing to a local network host (e.g., using 0.0.0.0, decimal IP notation, or DNS rebinding via nip.io) [1][2]. No authentication beyond being a recipient is required; the attacker only needs the ability to compose and send an HTML email. When the user views the message, Roundcube fetches the stylesheet resource from the attacker-controlled or internal address, triggering an outbound request from the server.
Impact
Successful exploitation allows the attacker to issue HTTP requests from the Roundcube server to internal network hosts (SSRF) or to gather information about the server's network environment. This can lead to information disclosure, such as probing internal services or reading responses from locally accessible endpoints. The attacker gains no direct code execution but may use the SSRF to chain further attacks against internal systems [1][2][3][4].
Mitigation
Fixed in Roundcube releases 1.7.1 (stable branch, dated 2026-05-25) and 1.6.16 (LTS branch, dated 2026-05-25) [3][4]. Users must upgrade to the respective fixed versions. No workaround is available other than applying the patch. The fix enhances IP address parsing in is_local_url() by adding ParseStringFlag options to handle non-decimal, non-quad-dotted, and compact IPv4 representations, and explicitly blocks 0.0.0.0 and resolves nip.io domains [1][2].
AI Insight generated on May 25, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
2- Range: >=1.6.14, <=1.6.16 || <1.7.1 start from 1.7.0
Patches
2cb3fc9041e91Fix SSRF bypass via specific local address URLs
3 files changed · +30 −2
CHANGELOG.md+1 −0 modified@@ -6,6 +6,7 @@ - Security: Fix stored XSS/HTML/CSS injection in subject field of the draft restore dialog - Security: Fix CSS injection bypass in HTML sanitizer via SVG `<animate attributeName="style">` - Security: Fix pre-auth SQL injection in `virtuser_query` plugin via preg_replace backslash escape bypass +- Security: Fix SSRF bypass via specific local address URLs ## Release 1.6.15
program/lib/Roundcube/rcube_utils.php+19 −2 modified@@ -1,6 +1,7 @@ <?php use IPLib\Factory; +use IPLib\ParseStringFlag; /* +-----------------------------------------------------------------------+ @@ -433,10 +434,25 @@ public static function is_local_url($url) $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 + $host = preg_replace('/^::ffff:/i', '', $host); + + if (preg_match('/([0-9a-f.-]+)\.nip\.io$/i', $host, $matches)) { + $host = trim($matches[1], '-.'); + } + // 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 = trim($host, '[]'))) { + 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 @@ -457,7 +473,8 @@ public static function is_local_url($url) } // FIXME: Should we accept any non-fqdn hostnames? - return (bool) preg_match('/^localhost(\.localdomain)?$/i', $host); + $host = strtolower($host); + return $host == 'metadata.google.internal' || preg_match('/^localhost(\.localdomain)?\.?$/', $host); } return false;
tests/Framework/Utils.php+10 −0 modified@@ -584,9 +584,19 @@ public static function provide_is_local_url_cases(): iterable ['//127.0.0.1', true], ['http://localhost', true], ['http://localhost.localdomain', true], + ['http://localhost.:8080/', true], + ['http://2130706433:8080', true], + ['http://0x7f000001:8080', true], + ['http://0177.0.0.1:8080', true], + ['http://127.1:8080', true], + ['http://0.0.0.0:8080', true], + ['http://[::ffff:127.0.0.1]:8080', true], + ['http://127.0.0.1.nip.io', true], + ['http://metadata.google.internal', true], // Non-local hosts ['http://[2001:470::76:0:0:0:2]', false], ['http://domain.tld', false], + ['http://20.0.0.1.nip.io', false], ]; }
ab96c88bfd88Fix SSRF bypass via specific local address URLs
3 files changed · +30 −2
CHANGELOG.md+1 −0 modified@@ -17,6 +17,7 @@ This file includes only changes we consider noteworthy for users, admins and plu - Security: Fix stored XSS/HTML/CSS injection in subject field of the draft restore dialog - Security: Fix CSS injection bypass in HTML sanitizer via SVG `<animate attributeName="style">` - Security: Fix pre-auth SQL injection in `virtuser_query` plugin via preg_replace backslash escape bypass +- Security: Fix SSRF bypass via specific local address URLs ## Release 1.7.0
program/lib/Roundcube/rcube_utils.php+19 −2 modified@@ -1,6 +1,7 @@ <?php use IPLib\Factory; +use IPLib\ParseStringFlag; /* +-----------------------------------------------------------------------+ @@ -428,10 +429,25 @@ public static function is_local_url($url) $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 + $host = preg_replace('/^::ffff:/i', '', $host); + + if (preg_match('/([0-9a-f.-]+)\.nip\.io$/i', $host, $matches)) { + $host = trim($matches[1], '-.'); + } + // 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 = trim($host, '[]'))) { + 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 @@ -445,7 +461,8 @@ public static function is_local_url($url) } // FIXME: Should we accept any non-fqdn hostnames? - return (bool) preg_match('/^localhost(\.localdomain)?$/i', $host); + $host = strtolower($host); + return $host == 'metadata.google.internal' || preg_match('/^localhost(\.localdomain)?\.?$/', $host); } return false;
tests/Framework/UtilsTest.php+10 −0 modified@@ -712,9 +712,19 @@ public static function provide_is_local_url_cases(): iterable ['//127.0.0.1', true], ['http://localhost', true], ['http://localhost.localdomain', true], + ['http://localhost.:8080/', true], + ['http://2130706433:8080', true], + ['http://0x7f000001:8080', true], + ['http://0177.0.0.1:8080', true], + ['http://127.1:8080', true], + ['http://0.0.0.0:8080', true], + ['http://[::ffff:127.0.0.1]:8080', true], + ['http://127.0.0.1.nip.io', true], + ['http://metadata.google.internal', true], // Non-local hosts ['http://[2001:470::76:0:0:0:2]', false], ['http://domain.tld', false], + ['http://20.0.0.1.nip.io', false], ]; }
Vulnerability mechanics
Root cause
"Insufficient IP address parsing in `is_local_url()` allowed many obfuscated local address forms to bypass the local-network check."
Attack vector
An attacker sends an HTML e-mail containing a CSS stylesheet link (or other URL) that uses an obfuscated local address representation. The `is_local_url()` function previously did not handle non-decimal IP formats (e.g., `2130706433` for 127.0.0.1), compact IPv4 notation (e.g., `127.1`), IPv4-mapped IPv6 addresses (e.g., `[::ffff:127.0.0.1]`), the `0.0.0.0` address, the `nip.io` DNS rebinding domain, or the GCP metadata hostname `metadata.google.internal` [patch_id=2473671][patch_id=2473672]. Because these forms were not recognized as local, the URL was allowed, causing Roundcube to fetch resources from internal hosts — leading to SSRF or information disclosure.
Affected code
The vulnerability resides in the `is_local_url()` method of `program/lib/Roundcube/rcube_utils.php` [patch_id=2473671][patch_id=2473672]. This function is responsible for determining whether a URL points to a local/private network address, and its insufficient sanitization allowed SSRF bypasses.
What the fix does
The patch adds `IPLib\ParseStringFlag` options so that `Factory::parseAddressString()` correctly interprets non-decimal, compact, and non-quad-dotted IPv4 representations [patch_id=2473671][patch_id=2473672]. It strips the IPv6-mapped prefix `::ffff:`, resolves `nip.io` DNS-rebinding hostnames back to their embedded IP, adds `0.0.0.0` to the local network list, and explicitly blocks `metadata.google.internal`. The `localhost` regex is also updated to accept a trailing dot (fully-qualified localhost). These changes close the bypass vectors that the previous fix for CVE-2026-35540 had missed.
Preconditions
- inputAttacker must be able to send an HTML e-mail to a Roundcube user
- configRoundcube must process CSS stylesheet links in HTML messages (default behavior)
Generated on May 25, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- github.com/roundcube/roundcubemail/commit/ab96c88bfd888866ec5e02190b19618db283923amitre
- github.com/roundcube/roundcubemail/commit/cb3fc9041e91640ba9ba49ee7b2147c176ebf5a1mitre
- github.com/roundcube/roundcubemail/releases/tag/1.6.16mitre
- github.com/roundcube/roundcubemail/releases/tag/1.7.1mitre
- roundcube.net/news/2026/05/24/security-updates-1.6.16-and-1.7.1mitre
News mentions
0No linked articles in our index yet.