Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/mail.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph Wurst <ChristophWurst@users.noreply.github.com>2021-06-22 20:27:06 +0300
committerGitHub <noreply@github.com>2021-06-22 20:27:06 +0300
commite2b1f1436bee18985b833de7b881b53033ac8718 (patch)
treee021013dad013dbe37c16af9bec9283f4d511753 /lib/Service
parented9ba94102e8596e8adc31197fa60c58338a09d7 (diff)
parent4bdcc023a36eca8000e08249cbaba086ee42a328 (diff)
Merge pull request #5189 from nextcloud/fix/noid/sanitize-css-style-sheets
Sanitize urls in css style sheets
Diffstat (limited to 'lib/Service')
-rwxr-xr-xlib/Service/Html.php54
-rwxr-xr-xlib/Service/HtmlPurify/TransformStyleURLs.php (renamed from lib/Service/HtmlPurify/TransformCSSBackground.php)12
2 files changed, 50 insertions, 16 deletions
diff --git a/lib/Service/Html.php b/lib/Service/Html.php
index 7983b35d3..feb36307e 100755
--- a/lib/Service/Html.php
+++ b/lib/Service/Html.php
@@ -7,6 +7,7 @@ declare(strict_types=1);
* @author Jakob Sack <jakob@owncloud.org>
* @author Jakob Sack <mail@jakobsack.de>
* @author Lukas Reschke <lukas@statuscode.ch>
+ * @author Richard Steinmetz <richard@steinmetz.cloud>
* @author Thomas Müller <thomas.mueller@tmit.eu>
*
* Mail
@@ -34,7 +35,7 @@ use HTMLPurifier_HTMLDefinition;
use HTMLPurifier_URIDefinition;
use HTMLPurifier_URISchemeRegistry;
use OCA\Mail\Service\HtmlPurify\CidURIScheme;
-use OCA\Mail\Service\HtmlPurify\TransformCSSBackground;
+use OCA\Mail\Service\HtmlPurify\TransformStyleURLs;
use OCA\Mail\Service\HtmlPurify\TransformHTMLLinks;
use OCA\Mail\Service\HtmlPurify\TransformImageSrc;
use OCA\Mail\Service\HtmlPurify\TransformNoReferrer;
@@ -42,6 +43,10 @@ use OCA\Mail\Service\HtmlPurify\TransformURLScheme;
use OCP\IRequest;
use OCP\IURLGenerator;
use OCP\Util;
+use Sabberworm\CSS\OutputFormat;
+use Sabberworm\CSS\Parser;
+use Sabberworm\CSS\Value\CSSString;
+use Sabberworm\CSS\Value\URL;
use Youthweb\UrlLinker\UrlLinker;
require_once __DIR__ . '/../../vendor/cerdic/css-tidy/class.csstidy.php';
@@ -134,7 +139,7 @@ class Html {
/** @var HTMLPurifier_HTMLDefinition $html */
$html = $config->getDefinition('HTML');
$html->info_attr_transform_post['imagesrc'] = new TransformImageSrc($this->urlGenerator);
- $html->info_attr_transform_post['cssbackground'] = new TransformCSSBackground($this->urlGenerator);
+ $html->info_attr_transform_post['cssbackground'] = new TransformStyleURLs($this->urlGenerator);
$html->info_attr_transform_post['htmllinks'] = new TransformHTMLLinks($this->urlGenerator);
/** @var HTMLPurifier_URIDefinition $uri */
@@ -143,22 +148,53 @@ class Html {
HTMLPurifier_URISchemeRegistry::instance()->register('cid', new CidURIScheme());
-
$purifier = new HTMLPurifier($config);
$result = $purifier->purify($mailBody);
// eat xml parse errors within HTMLPurifier
libxml_clear_errors();
- // Add back the style tag
+ // Sanitize CSS rules
$styles = $purifier->context->get('StyleBlocks');
if ($styles) {
- $result = implode("\n", [
- '<style type="text/css">',
- implode("\n", $styles),
- '</style>',
- $result,]);
+ $joinedStyles = implode("\n", $styles);
+ $result = $this->sanitizeStyleSheet($joinedStyles) . $result;
}
return $result;
}
+
+ /**
+ * Block all URLs in the given CSS style sheet and return a formatted html style tag.
+ *
+ * @param string $styles The CSS style sheet to sanitize.
+ * @return string Rendered style tag to be used in a html response.
+ */
+ public function sanitizeStyleSheet(string $styles): string {
+ $cssParser = new Parser($styles);
+ $css = $cssParser->parse();
+
+ // Replace urls with blocked image
+ $blockedUrl = new CSSString($this->urlGenerator->imagePath('mail', 'blocked-image.png'));
+ $hasBlockedContent = false;
+ foreach ($css->getAllValues() as $value) {
+ if ($value instanceof URL) {
+ $value->setURL($blockedUrl);
+ $hasBlockedContent = true;
+ }
+ }
+
+ // Save original styles to be able to restore them later
+ $savedStyles = '';
+ if ($hasBlockedContent) {
+ $savedStyles = 'data-original-content="' . htmlspecialchars($styles) . '"';
+ $styles = $css->render(OutputFormat::createCompact());
+ }
+
+ // Render style tag
+ return implode('', [
+ '<style type="text/css" ', $savedStyles, '>',
+ $styles,
+ '</style>',
+ ]);
+ }
}
diff --git a/lib/Service/HtmlPurify/TransformCSSBackground.php b/lib/Service/HtmlPurify/TransformStyleURLs.php
index 933a4803b..16b791db1 100755
--- a/lib/Service/HtmlPurify/TransformCSSBackground.php
+++ b/lib/Service/HtmlPurify/TransformStyleURLs.php
@@ -31,9 +31,9 @@ use HTMLPurifier_Context;
use OCP\IURLGenerator;
/**
- * Adds copies src to data-src on all img tags.
+ * Blocks urls in style attributes and backups original styles for restoring them later.
*/
-class TransformCSSBackground extends HTMLPurifier_AttrTransform {
+class TransformStyleURLs extends HTMLPurifier_AttrTransform {
/** @var IURLGenerator */
private $urlGenerator;
@@ -49,8 +49,7 @@ class TransformCSSBackground extends HTMLPurifier_AttrTransform {
* @return array
*/
public function transform($attr, $config, $context) {
- if (!isset($attr['style']) ||
- strpos($attr['style'], 'background') === false) {
+ if (!isset($attr['style']) || strpos($attr['style'], 'url(') === false) {
return $attr;
}
@@ -64,10 +63,9 @@ class TransformCSSBackground extends HTMLPurifier_AttrTransform {
}
[$name, $value] = explode(':', $cssAttribute, 2);
- if (strpos($name, 'background') !== false &&
- strpos($value, 'url(') !== false) {
+ if (strpos($value, 'url(') !== false) {
// Replace image URL
- $value = preg_replace('/url\("?http.*\)/i',
+ $value = preg_replace('/url\(("|\')?http.*\)/i',
'url(' . $this->urlGenerator->imagePath('mail', 'blocked-image.png') . ')',
$value);
return $name . ':' . $value;