Skip to content

Commit

Permalink
Fix cross-site scripting (XSS) vulnerability in handling of linkrefs …
Browse files Browse the repository at this point in the history
…in plain text messages

Thanks to Niraj Shivtarkar for the report.
  • Loading branch information
alecpl committed Sep 14, 2023
1 parent 401eae0 commit fe42e14
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 8 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -2,6 +2,7 @@

## Unreleased

- Fix cross-site scripting (XSS) vulnerability in handling of linkrefs in plain text messages
- Fix so output of log_date_format with microseconds contains time in server time zone, not UTC
- Fix so N property always exists in a vCard export (#8771)
- Fix so rcmail::format_date() works with DateTimeImmutable input (#8867)
Expand Down
6 changes: 3 additions & 3 deletions program/lib/Roundcube/rcube_string_replacer.php
Expand Up @@ -59,8 +59,8 @@ function __construct($options = [])
$link_prefix = "([\w]+:\/\/|{$this->noword}[Ww][Ww][Ww]\.|^[Ww][Ww][Ww]\.)";

$this->options = $options;
$this->linkref_index = '/\[([^\]#]+)\](:?\s*' . substr($this->pattern, 1, -1) . ')/';
$this->linkref_pattern = '/\[([^\]#]+)\]/';
$this->linkref_index = '/\[([^<>\]#]+)\](:?\s*' . substr($this->pattern, 1, -1) . ')/';
$this->linkref_pattern = '/\[([^<>\]#]+)\]/';
$this->link_pattern = "/$link_prefix($utf_domain([$url1]*[$url2]+)*)/";
$this->mailto_pattern = "/("
. "[-\w!\#\$%&*+~\/^`|{}=]+(?:\.[-\w!\#\$%&*+~\/^`|{}=]+)*" // local-part
Expand Down Expand Up @@ -152,7 +152,7 @@ protected function linkref_addindex($matches)
$matches[0][1]
];

return $this->get_replacement($this->add('['.$key.']')) . $matches[2][0];
return $this->get_replacement($this->add('[' . $key . ']')) . $matches[2][0];
}

/**
Expand Down
12 changes: 7 additions & 5 deletions tests/Framework/StringReplacer.php
Expand Up @@ -63,19 +63,21 @@ function test_replace($input, $output)
$this->assertEquals($output, $result);
}

/**
* Test link references
*/
function test_linkrefs()
{
$input = "This is a sample message [1] to test the new linkref [ref0] replacement feature of [Roundcube].\n";
$input.= "\n";
$input.= "[1] http://en.wikipedia.org/wiki/Email\n";
$input.= "[ref0] www.link-ref.com\n";
$input = "This is a sample message [1] to test the linkref [ref0] replacement feature of [Roundcube].[ref<0]\n"
. "[1] http://en.wikipedia.org/wiki/Email\n"
. "[ref0] www.link-ref.com\n";

$replacer = new rcube_string_replacer;
$result = $replacer->replace($input);
$result = $replacer->resolve($result);

$this->assertContains('[<a href="http://en.wikipedia.org/wiki/Email">1</a>] to', $result, "Numeric linkref replacements");
$this->assertContains('[<a href="http://www.link-ref.com">ref0</a>] repl', $result, "Alphanum linkref replacements");
$this->assertContains('of [Roundcube].', $result, "Don't touch strings without an index entry");
$this->assertContains('of [Roundcube].[ref<0]', $result, "Don't touch strings without an index entry");
}
}
17 changes: 17 additions & 0 deletions tests/Framework/Text2Html.php
Expand Up @@ -137,6 +137,23 @@ function test_text2html_xss()
$this->assertEquals($expected, $html);
}

/**
* Test XSS issue
*/
function test_text2html_xss2()
{
$input = "\n[<script>evil</script>] https://google.com\n";
$t2h = new rcube_text2html($input);

$html = $t2h->get_html();

$expected = "<div class=\"pre\"><br>\n[&lt;script&gt;evil&lt;/script&gt;] "
. "<a rel=\"noreferrer\" target=\"_blank\" href=\"https://google.com\">https://google.com</a><br>\n"
. "</div>";

$this->assertEquals($expected, $html);
}

/**
* Test bug #8021
*/
Expand Down

0 comments on commit fe42e14

Please sign in to comment.