Critical severityCISA KEVNVD Advisory· Published Jun 2, 2025· Updated Feb 21, 2026
CVE-2025-49113
CVE-2025-49113
Description
Roundcube Webmail before 1.5.10 and 1.6.x before 1.6.11 allows remote code execution by authenticated users because the _from parameter in a URL is not validated in program/actions/settings/upload.php, leading to PHP Object Deserialization.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
roundcube/roundcubemailPackagist | < 1.5.10 | 1.5.10 |
roundcube/roundcubemailPackagist | >= 1.6.0, < 1.6.11 | 1.6.11 |
Affected products
1Patches
3c50a07d88ca3Use get_input_string()
1 file changed · +2 −2
program/actions/settings/upload.php+2 −2 modified@@ -29,7 +29,7 @@ class rcmail_action_settings_upload extends rcmail_action public function run($args = []) { $rcmail = rcmail::get_instance(); - $from = rcube_utils::get_input_value('_from', rcube_utils::INPUT_GET); + $from = rcube_utils::get_input_string('_from', rcube_utils::INPUT_GET); $type = preg_replace('/(add|edit)-/', '', $from); // Validate URL input. @@ -51,7 +51,7 @@ public function run($args = []) $rcmail->output->reset(); $max_size = $rcmail->config->get($type . '_image_size', 64) * 1024; - $uploadid = rcube_utils::get_input_value('_uploadid', rcube_utils::INPUT_GET); + $uploadid = rcube_utils::get_input_string('_uploadid', rcube_utils::INPUT_GET); if (!empty($_FILES['_file']['tmp_name']) && is_array($_FILES['_file']['tmp_name'])) { $multiple = count($_FILES['_file']['tmp_name']) > 1;
7408f3137966Validate URL parameter in upload code (#9866)
3 files changed · +42 −0
program/actions/settings/upload.php+7 −0 modified@@ -32,6 +32,13 @@ public function run($args = []) $from = rcube_utils::get_input_value('_from', rcube_utils::INPUT_GET); $type = preg_replace('/(add|edit)-/', '', $from); + // Validate URL input. + if (!rcube_utils::is_simple_string($type)) { + rcmail::write_log('errors', 'The URL parameter "_from" contains disallowed characters and the request is thus rejected.'); + $rcmail->output->command('display_message', 'Invalid input', 'error'); + $rcmail->output->send('iframe'); + } + // Plugins in Settings may use this file for some uploads (#5694) // Make sure it does not contain a dot, which is a special character // when using rcube_session::append() below
program/lib/Roundcube/rcube_utils.php+16 −0 modified@@ -291,6 +291,22 @@ public static function get_input_string($fname, $source, $allow_html = false, $c return is_string($value) ? $value : ''; } + /** + * Check if input value is a "simple" string. + * "Simple" is defined as a non-empty string containing only + * - "word" characters (alphanumeric plus underscore), + * - dots, + * - dashes. + * + * @param string $input The string to test + * + * @return bool + */ + public static function is_simple_string($input) + { + return is_string($input) && !!preg_match('/^[\w.-]+$/i', $input); + } + /** * Read request parameter value and convert it for internal use * Performs stripslashes() and charset conversion if necessary
tests/Framework/Utils.php+19 −0 modified@@ -503,6 +503,25 @@ function test_get_input_string() $this->assertSame('', rcube_utils::get_input_string('test', rcube_utils::INPUT_GET)); } + /** + * rcube_utils::is_simple_string() + */ + function test_is_simple_string() + { + $this->assertTrue(rcube_utils::is_simple_string('some-thing.123_')); + $this->assertFalse(rcube_utils::is_simple_string('')); + $this->assertFalse(rcube_utils::is_simple_string(' ')); + $this->assertFalse(rcube_utils::is_simple_string('some–thing')); + $this->assertFalse(rcube_utils::is_simple_string('some=thing')); + $this->assertFalse(rcube_utils::is_simple_string('some thing')); + $this->assertFalse(rcube_utils::is_simple_string('some!thing')); + $this->assertFalse(rcube_utils::is_simple_string('%20')); + $this->assertFalse(rcube_utils::is_simple_string('\0000')); + $this->assertFalse(rcube_utils::is_simple_string(1)); + $this->assertFalse(rcube_utils::is_simple_string(new stdClass())); + $this->assertFalse(rcube_utils::is_simple_string(null)); + } + /** * rcube:utils::file2class() */
0376f69e958aValidate URL parameter in upload code (#9866)
3 files changed · +42 −0
program/actions/settings/upload.php+7 −0 modified@@ -32,6 +32,13 @@ public function run($args = []) $from = rcube_utils::get_input_string('_from', rcube_utils::INPUT_GET); $type = preg_replace('/(add|edit)-/', '', $from); + // Validate URL input. + if (!rcube_utils::is_simple_string($type)) { + rcmail::write_log('errors', 'The URL parameter "_from" contains disallowed characters and the request is thus rejected.'); + $rcmail->output->command('display_message', 'Invalid input', 'error'); + $rcmail->output->send('iframe'); + } + // Plugins in Settings may use this file for some uploads (#5694) // Make sure it does not contain a dot, which is a special character // when using rcube_session::append() below
program/lib/Roundcube/rcube_utils.php+16 −0 modified@@ -285,6 +285,22 @@ public static function get_input_string($fname, $source, $allow_html = false, $c return is_string($value) ? $value : ''; } + /** + * Check if input value is a "simple" string. + * "Simple" is defined as a non-empty string containing only + * - "word" characters (alphanumeric plus underscore), + * - dots, + * - dashes. + * + * @param string $input The string to test + * + * @return bool + */ + public static function is_simple_string($input) + { + return is_string($input) && !!preg_match('/^[\w.-]+$/i', $input); + } + /** * Read request parameter value and convert it for internal use * Performs stripslashes() and charset conversion if necessary
tests/Framework/Utils.php+19 −0 modified@@ -503,6 +503,25 @@ function test_get_input_string() $this->assertSame('', rcube_utils::get_input_string('test', rcube_utils::INPUT_GET)); } + /** + * rcube_utils::is_simple_string() + */ + function test_is_simple_string() + { + $this->assertTrue(rcube_utils::is_simple_string('some-thing.123_')); + $this->assertFalse(rcube_utils::is_simple_string('')); + $this->assertFalse(rcube_utils::is_simple_string(' ')); + $this->assertFalse(rcube_utils::is_simple_string('some–thing')); + $this->assertFalse(rcube_utils::is_simple_string('some=thing')); + $this->assertFalse(rcube_utils::is_simple_string('some thing')); + $this->assertFalse(rcube_utils::is_simple_string('some!thing')); + $this->assertFalse(rcube_utils::is_simple_string('%20')); + $this->assertFalse(rcube_utils::is_simple_string('\0000')); + $this->assertFalse(rcube_utils::is_simple_string(1)); + $this->assertFalse(rcube_utils::is_simple_string(new stdClass())); + $this->assertFalse(rcube_utils::is_simple_string(null)); + } + /** * rcube:utils::file2class() */
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
15- github.com/advisories/GHSA-8j8w-wwqc-x596ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2025-49113ghsaADVISORY
- www.openwall.com/lists/oss-security/2025/06/02/3ghsaWEB
- fearsoff.org/research/roundcubeghsaWEB
- github.com/roundcube/roundcubemail/commit/0376f69e958a8fef7f6f09e352c541b4e7729c4dghsaWEB
- github.com/roundcube/roundcubemail/commit/7408f31379666124a39f9cb1018f62bc5e2dc695ghsaWEB
- github.com/roundcube/roundcubemail/commit/c50a07d88ca38f018a0f4a0b008e9a1deb32637eghsaWEB
- github.com/roundcube/roundcubemail/pull/9865ghsaWEB
- github.com/roundcube/roundcubemail/releases/tag/1.5.10ghsaWEB
- github.com/roundcube/roundcubemail/releases/tag/1.6.11ghsaWEB
- lists.debian.org/debian-lts-announce/2025/06/msg00008.htmlghsaWEB
- roundcube.net/news/2025/06/01/security-updates-1.6.11-and-1.5.10ghsaWEB
- www.cisa.gov/known-exploited-vulnerabilities-catalogghsaWEB
- www.vicarius.io/vsociety/posts/cve-2025-49113-roundcube-mitigation-scriptghsaWEB
- www.vicarius.io/vsociety/posts/cve-2025-49113-roundcube-vulnerability-detectionghsaWEB
News mentions
0No linked articles in our index yet.