From c506e6fb7fc02514eb0a9b2bcfdac4f1160f7a57 Mon Sep 17 00:00:00 2001 From: Oliver Hader <oliver@typo3.org> Date: Sun, 11 Jul 2021 13:46:59 +0200 Subject: [PATCH] [TASK] Introduce SVG Sanitizer This change introduces behavior of extension `t3g/svg-sanitizer` into the TYPO3 core. Sanitizing SVG data is actually done by external package `enshrined/svg-sanitize` by Daryll Doyle. The following aspects are introduced: + handle `GeneralUtility::upload_copy_move` invocations + handle FAL action events `file-add`, `file-replace`, `set-content` + provide upgrade wizard, sanitizing all SVG files in storages that are using `LocalDriver` Custom usage: ``` $sanitizer = new \TYPO3\CMS\Core\Resource\Security\SvgSanitizer(); $sanitizer->sanitizeFile($sourcePath, $targetPath); $svg = $sanitizer->sanitizeContent($svg); ``` Basically this change enforces following public service announcements concerning SVG files, to enhance these security aspects per default: + https://typo3.org/security/advisory/typo3-psa-2020-003 + https://typo3.org/security/advisory/typo3-psa-2019-010 Resolves: #94492 Releases: master, 10.4, 9.5 Change-Id: I42c206190d8a335ebaf77b7e5d57b383e3bcbae1 Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/69809 Tested-by: core-ci <typo3@b13.com> Tested-by: Benni Mack <benni@typo3.org> Tested-by: Oliver Bartsch <bo@cedev.de> Tested-by: Oliver Hader <oliver.hader@typo3.org> Reviewed-by: Benni Mack <benni@typo3.org> Reviewed-by: Oliver Bartsch <bo@cedev.de> Reviewed-by: Oliver Hader <oliver.hader@typo3.org> --- composer.json | 1 + composer.lock | 47 +++- .../Resource/Security/SvgEventListener.php | 72 +++++++ .../Resource/Security/SvgHookHandler.php | 48 +++++ .../Resource/Security/SvgSanitizer.php | 56 +++++ .../Resource/Security/SvgTypeCheck.php | 76 +++++++ typo3/sysext/core/Configuration/Services.yaml | 21 ++ .../Important-94492-IntroduceSVGSanitizer.rst | 39 ++++ .../Fixtures/CleanSVG/TYPO3_Logo_Clean.svg | 7 + .../Fixtures/CleanSVG/TYPO3_Logo_Data.svg | 8 + .../Fixtures/CleanSVG/TYPO3_Logo_Script.svg | 7 + .../Resource/Fixtures/CleanSVG/ariaData.svg | 57 +++++ .../Fixtures/CleanSVG/billion_laughs.svg | 0 .../Resource/Fixtures/CleanSVG/entity.svg | 4 + .../Resource/Fixtures/CleanSVG/entity_2.svg | 4 + .../Resource/Fixtures/CleanSVG/external.svg | 10 + .../Resource/Fixtures/CleanSVG/hrefOne.svg | 13 ++ .../Resource/Fixtures/CleanSVG/hrefTwo.svg | 13 ++ .../Resource/Fixtures/CleanSVG/html.svg | 4 + .../Resource/Fixtures/CleanSVG/simple.svg | 4 + .../Resource/Fixtures/CleanSVG/svgOne.svg | 13 ++ .../Resource/Fixtures/CleanSVG/use.svg | 6 + .../Resource/Fixtures/CleanSVG/useDos.svg | 113 ++++++++++ .../Fixtures/CleanSVG/xlinkLaughs.svg | 71 +++++++ .../Resource/Fixtures/CleanSVG/xlinkLoop.svg | 24 +++ .../Fixtures/CleanSVG/xlink_laughs.svg | 146 +++++++++++++ .../Resource/Fixtures/CleanSVG/xmlOne.xml | 11 + .../Resource/Fixtures/CleanSVG/xss.svg | 4 + .../Fixtures/DirtySVG/TYPO3_Logo_Clean.svg | 7 + .../Fixtures/DirtySVG/TYPO3_Logo_Data.svg | 8 + .../Fixtures/DirtySVG/TYPO3_Logo_Script.svg | 13 ++ .../Resource/Fixtures/DirtySVG/ariaData.svg | 56 +++++ .../Fixtures/DirtySVG/billion_laughs.svg | 16 ++ .../Resource/Fixtures/DirtySVG/entity.svg | 5 + .../Resource/Fixtures/DirtySVG/entity_2.svg | 8 + .../Resource/Fixtures/DirtySVG/external.svg | 11 + .../Resource/Fixtures/DirtySVG/hrefOne.svg | 13 ++ .../Resource/Fixtures/DirtySVG/hrefTwo.svg | 13 ++ .../Resource/Fixtures/DirtySVG/html.svg | 14 ++ .../Resource/Fixtures/DirtySVG/simple.svg | 5 + .../Resource/Fixtures/DirtySVG/svgOne.svg | 15 ++ .../Resource/Fixtures/DirtySVG/use.svg | 5 + .../Resource/Fixtures/DirtySVG/useDos.svg | 129 +++++++++++ .../Fixtures/DirtySVG/xlinkLaughs.svg | 146 +++++++++++++ .../Resource/Fixtures/DirtySVG/xlinkLoop.svg | 31 +++ .../Fixtures/DirtySVG/xlink_laughs.svg | 146 +++++++++++++ .../Resource/Fixtures/DirtySVG/xmlOne.xml | 12 ++ .../Resource/Fixtures/DirtySVG/xss.svg | 8 + .../Resource/Security/SvgSanitizerTest.php | 60 ++++++ typo3/sysext/core/composer.json | 1 + typo3/sysext/core/ext_localconf.php | 1 + .../Classes/Updates/SvgFilesSanitization.php | 200 ++++++++++++++++++ typo3/sysext/install/ext_localconf.php | 2 + 53 files changed, 1803 insertions(+), 1 deletion(-) create mode 100644 typo3/sysext/core/Classes/Resource/Security/SvgEventListener.php create mode 100644 typo3/sysext/core/Classes/Resource/Security/SvgHookHandler.php create mode 100644 typo3/sysext/core/Classes/Resource/Security/SvgSanitizer.php create mode 100644 typo3/sysext/core/Classes/Resource/Security/SvgTypeCheck.php create mode 100644 typo3/sysext/core/Documentation/Changelog/9.5.x/Important-94492-IntroduceSVGSanitizer.rst create mode 100644 typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/TYPO3_Logo_Clean.svg create mode 100644 typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/TYPO3_Logo_Data.svg create mode 100644 typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/TYPO3_Logo_Script.svg create mode 100644 typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/ariaData.svg create mode 100644 typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/billion_laughs.svg create mode 100644 typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/entity.svg create mode 100644 typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/entity_2.svg create mode 100644 typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/external.svg create mode 100644 typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/hrefOne.svg create mode 100644 typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/hrefTwo.svg create mode 100644 typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/html.svg create mode 100644 typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/simple.svg create mode 100644 typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/svgOne.svg create mode 100644 typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/use.svg create mode 100644 typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/useDos.svg create mode 100644 typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/xlinkLaughs.svg create mode 100644 typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/xlinkLoop.svg create mode 100644 typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/xlink_laughs.svg create mode 100644 typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/xmlOne.xml create mode 100644 typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/xss.svg create mode 100644 typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/TYPO3_Logo_Clean.svg create mode 100644 typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/TYPO3_Logo_Data.svg create mode 100644 typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/TYPO3_Logo_Script.svg create mode 100644 typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/ariaData.svg create mode 100644 typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/billion_laughs.svg create mode 100644 typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/entity.svg create mode 100644 typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/entity_2.svg create mode 100644 typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/external.svg create mode 100644 typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/hrefOne.svg create mode 100644 typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/hrefTwo.svg create mode 100644 typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/html.svg create mode 100644 typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/simple.svg create mode 100644 typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/svgOne.svg create mode 100644 typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/use.svg create mode 100644 typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/useDos.svg create mode 100644 typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/xlinkLaughs.svg create mode 100644 typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/xlinkLoop.svg create mode 100644 typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/xlink_laughs.svg create mode 100644 typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/xmlOne.xml create mode 100644 typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/xss.svg create mode 100644 typo3/sysext/core/Tests/Functional/Resource/Security/SvgSanitizerTest.php create mode 100644 typo3/sysext/install/Classes/Updates/SvgFilesSanitization.php diff --git a/composer.json b/composer.json index f183ac9867a1..b971524ccd03 100644 --- a/composer.json +++ b/composer.json @@ -46,6 +46,7 @@ "doctrine/instantiator": "^1.4", "doctrine/lexer": "^1.2.1", "egulias/email-validator": "^2.1", + "enshrined/svg-sanitize": "^0.14.0", "guzzlehttp/guzzle": "^7.2", "guzzlehttp/psr7": "^1.7.0", "nikic/php-parser": "^4.10.4", diff --git a/composer.lock b/composer.lock index 8e71965b2b3a..681ad2f12324 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "ca0cef227667409039995378723d0f49", + "content-hash": "4cac8f22e93753a4a2a91e19b3ffaa4e", "packages": [ { "name": "bacon/bacon-qr-code", @@ -815,6 +815,51 @@ ], "time": "2020-12-29T14:50:06+00:00" }, + { + "name": "enshrined/svg-sanitize", + "version": "0.14.0", + "source": { + "type": "git", + "url": "https://github.com/darylldoyle/svg-sanitizer.git", + "reference": "beff89576a72540ee99476aeb9cfe98222e76fb8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/darylldoyle/svg-sanitizer/zipball/beff89576a72540ee99476aeb9cfe98222e76fb8", + "reference": "beff89576a72540ee99476aeb9cfe98222e76fb8", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*" + }, + "require-dev": { + "codeclimate/php-test-reporter": "^0.1.2", + "phpunit/phpunit": "^6" + }, + "type": "library", + "autoload": { + "psr-4": { + "enshrined\\svgSanitize\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "authors": [ + { + "name": "Daryll Doyle", + "email": "daryll@enshrined.co.uk" + } + ], + "description": "An SVG sanitizer for PHP", + "support": { + "issues": "https://github.com/darylldoyle/svg-sanitizer/issues", + "source": "https://github.com/darylldoyle/svg-sanitizer/tree/0.14.0" + }, + "time": "2021-01-21T10:13:20+00:00" + }, { "name": "guzzlehttp/guzzle", "version": "7.2.0", diff --git a/typo3/sysext/core/Classes/Resource/Security/SvgEventListener.php b/typo3/sysext/core/Classes/Resource/Security/SvgEventListener.php new file mode 100644 index 000000000000..41ddf496da59 --- /dev/null +++ b/typo3/sysext/core/Classes/Resource/Security/SvgEventListener.php @@ -0,0 +1,72 @@ +<?php + +declare(strict_types=1); + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +namespace TYPO3\CMS\Core\Resource\Security; + +use TYPO3\CMS\Core\Resource\Event\AfterFileContentsSetEvent; +use TYPO3\CMS\Core\Resource\Event\BeforeFileAddedEvent; +use TYPO3\CMS\Core\Resource\Event\BeforeFileReplacedEvent; + +class SvgEventListener +{ + /** + * @var SvgSanitizer + */ + protected $sanitizer; + + /** + * @var SvgTypeCheck + */ + protected $typeCheck; + + public function __construct(SvgSanitizer $sanitizer, SvgTypeCheck $typeCheck) + { + $this->sanitizer = $sanitizer; + $this->typeCheck = $typeCheck; + } + + public function beforeFileAdded(BeforeFileAddedEvent $event): void + { + $filePath = $event->getSourceFilePath(); + if ($this->typeCheck->forFilePath($filePath)) { + $this->sanitizer->sanitizeFile($filePath); + } + } + + public function beforeFileReplaced(BeforeFileReplacedEvent $event): void + { + $filePath = $event->getLocalFilePath(); + if ($this->typeCheck->forFilePath($filePath)) { + $this->sanitizer->sanitizeFile($filePath); + } + } + + public function afterFileContentsSet(AfterFileContentsSetEvent $event): void + { + $file = $event->getFile(); + if (!$this->typeCheck->forResource($file)) { + return; + } + $content = $event->getContent(); + $sanitizedContent = $this->sanitizer->sanitizeContent($content); + // cave: setting content will trigger calling this handler again + // (having custom-flags on `FileInterface` would allow to mark it as "processed") + if ($sanitizedContent !== $content) { + $file->setContents($sanitizedContent); + } + } +} diff --git a/typo3/sysext/core/Classes/Resource/Security/SvgHookHandler.php b/typo3/sysext/core/Classes/Resource/Security/SvgHookHandler.php new file mode 100644 index 000000000000..26f050c9e5ef --- /dev/null +++ b/typo3/sysext/core/Classes/Resource/Security/SvgHookHandler.php @@ -0,0 +1,48 @@ +<?php + +declare(strict_types=1); + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +namespace TYPO3\CMS\Core\Resource\Security; + +class SvgHookHandler +{ + /** + * @var SvgSanitizer + */ + protected $sanitizer; + + /** + * @var SvgTypeCheck + */ + protected $typeCheck; + + public function __construct(SvgSanitizer $sanitizer, SvgTypeCheck $typeCheck) + { + $this->sanitizer = $sanitizer; + $this->typeCheck = $typeCheck; + } + + /** + * @param array $parameters + */ + public function processMoveUploadedFile(array $parameters) + { + $filePath = $parameters['source'] ?? null; + if ($filePath !== null && $this->typeCheck->forFilePath($filePath)) { + $this->sanitizer->sanitizeFile($filePath); + } + } +} diff --git a/typo3/sysext/core/Classes/Resource/Security/SvgSanitizer.php b/typo3/sysext/core/Classes/Resource/Security/SvgSanitizer.php new file mode 100644 index 000000000000..373ade783bf1 --- /dev/null +++ b/typo3/sysext/core/Classes/Resource/Security/SvgSanitizer.php @@ -0,0 +1,56 @@ +<?php + +declare(strict_types=1); + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +namespace TYPO3\CMS\Core\Resource\Security; + +use enshrined\svgSanitize\Sanitizer; + +class SvgSanitizer +{ + /** + * @param string $sourcePath + * @param string|null $targetPath + * @throws \BadFunctionCallException + */ + public function sanitizeFile(string $sourcePath, string $targetPath = null): void + { + if ($targetPath === null) { + $targetPath = $sourcePath; + } + $svg = file_get_contents($sourcePath); + if (!is_string($svg)) { + return; + } + $sanitizedSvg = $this->sanitizeContent($svg); + if ($sanitizedSvg !== $svg) { + file_put_contents($targetPath, $sanitizedSvg); + } + } + + /** + * @param string $svg + * + * @return string + * @throws \BadFunctionCallException + */ + public function sanitizeContent(string $svg): string + { + $sanitizer = new Sanitizer(); + $sanitizer->removeRemoteReferences(true); + return $sanitizer->sanitize($svg) ?: ''; + } +} diff --git a/typo3/sysext/core/Classes/Resource/Security/SvgTypeCheck.php b/typo3/sysext/core/Classes/Resource/Security/SvgTypeCheck.php new file mode 100644 index 000000000000..66509f620564 --- /dev/null +++ b/typo3/sysext/core/Classes/Resource/Security/SvgTypeCheck.php @@ -0,0 +1,76 @@ +<?php + +declare(strict_types=1); + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +namespace TYPO3\CMS\Core\Resource\Security; + +use TYPO3\CMS\Core\Resource\FileInterface; +use TYPO3\CMS\Core\Resource\MimeTypeDetector; +use TYPO3\CMS\Core\Type\File\FileInfo; +use TYPO3\CMS\Core\Utility\GeneralUtility; + +class SvgTypeCheck +{ + protected const MIME_TYPES = ['image/svg', 'image/svg+xml', 'application/svg', 'application/svg+xml']; + + /** + * @var MimeTypeDetector + */ + protected $mimeTypeDetector; + + /** + * @var string[] + */ + protected $fileExtensions; + + public function __construct(MimeTypeDetector $mimeTypeDetector) + { + $this->mimeTypeDetector = $mimeTypeDetector; + $this->fileExtensions = $this->resolveFileExtensions(); + } + + public function forFilePath(string $filePath): bool + { + $fileInfo = GeneralUtility::makeInstance(FileInfo::class, $filePath); + $fileExtension = $fileInfo->getExtension(); + $mimeType = $fileInfo->getMimeType(); + return in_array($fileExtension, $this->fileExtensions, true) + || in_array($mimeType, self::MIME_TYPES, true); + } + + public function forResource(FileInterface $file): bool + { + $fileExtension = $file->getExtension(); + $mimeType = $file->getMimeType(); + return in_array($fileExtension, $this->fileExtensions, true) + || in_array($mimeType, self::MIME_TYPES, true); + } + + /** + * @return string[] + */ + protected function resolveFileExtensions(): array + { + $fileExtensions = array_map( + function (string $mimeType): array { + return $this->mimeTypeDetector->getFileExtensionsForMimeType($mimeType); + }, + self::MIME_TYPES + ); + $fileExtensions = array_filter($fileExtensions); + return count($fileExtensions) > 0 ? array_unique(array_merge(...$fileExtensions)) : []; + } +} diff --git a/typo3/sysext/core/Configuration/Services.yaml b/typo3/sysext/core/Configuration/Services.yaml index 2ecbf55025b7..341d5462a2c5 100644 --- a/typo3/sysext/core/Configuration/Services.yaml +++ b/typo3/sysext/core/Configuration/Services.yaml @@ -187,6 +187,27 @@ services: identifier: 'synchronize-filemounts-after-folder-renamed' method: 'synchronizeFilemountsAfterRename' + TYPO3\CMS\Core\Resource\Security\SvgEventListener: + tags: + - name: event.listener + identifier: 'svg-resource-storage-listener-before-file-added' + method: 'beforeFileAdded' + event: TYPO3\CMS\Core\Resource\Event\BeforeFileAddedEvent + - name: event.listener + identifier: 'svg-resource-storage-listener-before-file-replaced' + method: 'beforeFileReplaced' + event: TYPO3\CMS\Core\Resource\Event\BeforeFileReplacedEvent + - name: event.listener + identifier: 'svg-resource-storage-listener-after-file-content-set' + method: 'afterFileContentsSet' + event: TYPO3\CMS\Core\Resource\Event\AfterFileContentsSetEvent + + TYPO3\CMS\Core\Resource\Security\SvgHookHandler: + public: true + + TYPO3\CMS\Core\Resource\Security\SvgTypeCheck: + public: true + # Core caches, cache.core and cache.assets are injected as early # entries in TYPO3\CMS\Core\Core\Bootstrap and therefore omitted here cache.hash: diff --git a/typo3/sysext/core/Documentation/Changelog/9.5.x/Important-94492-IntroduceSVGSanitizer.rst b/typo3/sysext/core/Documentation/Changelog/9.5.x/Important-94492-IntroduceSVGSanitizer.rst new file mode 100644 index 000000000000..60813267c3df --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/9.5.x/Important-94492-IntroduceSVGSanitizer.rst @@ -0,0 +1,39 @@ +.. include:: ../../Includes.txt + +=========================================== +Important: #94492 - Introduce SVG Sanitizer +=========================================== + +See :issue:`94492` + +Description +=========== + +SVG sanitization behavior of extension [`t3g/svg-sanitizer`](https://packagist.org/packages/t3g/svg-sanitizer) +has been introduced into TYPO3 core. Actual processing is done by low-level sanitization package +[`enshrined/svg-sanitize`](https://packagist.org/packages/enshrined/svg-sanitize) by Daryll Doyle. + +Introduced aspects +------------------ + +* handle :php:`GeneralUtility::upload_copy_move` invocations +* handle FAL action events `file-add`, `file-replace`, `set-content` +* provide upgrade wizard, sanitizing all SVG files in storages that + are using :php:`\TYPO3\CMS\Core\Resource\Driver\LocalDriver` + +Custom usage +------------ + +.. code-block:: php + + $sanitizer = new \TYPO3\CMS\Core\Resource\Security\SvgSanitizer(); + $sanitizer->sanitizeFile($sourcePath, $targetPath); + $svg = $sanitizer->sanitizeContent($svg); + +Basically this change enforces following public service announcements +concerning SVG files, to enhance these security aspects per default: + +* [TYPO3-PSA-2020-003: Mitigation of Cross-Site Scripting Vulnerabilities in File Upload Handling](https://typo3.org/security/advisory/typo3-psa-2020-003) +* [TYPO3-PSA-2019-010: Cross-Site Scripting Vulnerabilities in File Upload Handling](https://typo3.org/security/advisory/typo3-psa-2019-010) + +.. index:: Backend, FAL, Frontend, ext:core diff --git a/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/TYPO3_Logo_Clean.svg b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/TYPO3_Logo_Clean.svg new file mode 100644 index 000000000000..01db9ad346d1 --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/TYPO3_Logo_Clean.svg @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" id="Ebene_1" x="0px" y="0px" width="400px" height="168px" viewBox="0 0 400 168"> + <rect x="0.404" y="0.412" fill="none" width="400" height="168"></rect> + <path d="M164.458,70.495v55.187h-7.691V70.495h-13.622v-6.72h34.934v6.72H164.458z M205.737,96.935v28.747h-7.966V96.935 	l-15.825-33.16h8.485l11.668,25.02l11.676-25.02h8.053L205.737,96.935z M245.705,102.332h-7.429v23.35h-7.698V63.775 	c0,0,7.613-0.625,14.956-0.625c13.438,0,17.331,8.316,17.331,19.195C262.865,95.785,258.261,102.332,245.705,102.332 	 M246.585,69.522c-4.859,0-8.31,0.531-8.31,0.531v25.815h8.31c4.956,0,8.409-3.268,8.409-12.907 	C254.995,74.114,252.863,69.522,246.585,69.522 M290.635,126.295c-14.588,0-18.481-10.61-18.481-32.271 	c0-20.789,3.894-30.873,18.481-30.873c14.587,0,18.478,10.084,18.478,30.873C309.113,115.685,305.222,126.295,290.635,126.295 	 M290.635,69.605c-7.953,0-10.611,5.4-10.611,24.858c0,19.006,2.658,25.383,10.611,25.383s10.61-6.377,10.61-25.383 	C301.246,75.005,298.588,69.605,290.635,69.605 M331.313,126.295c-4.331,0-10.78-1.321-11.587-1.51v-6.444 	c2.129,0.438,7.608,1.349,11.503,1.349c4.501,0,7.428-3.822,7.428-10.64c0-8.039-1.318-12.286-7.601-12.286H323.8v-6.463h6.362 	c7.176,0,7.515-7.34,7.515-10.873c0-6.99-2.202-9.823-6.621-9.823c-3.89,0-8.323,0.973-10.879,1.506v-6.454 	c0.967-0.179,6.193-1.506,10.696-1.506c9.105,0,14.332,3.892,14.332,17.075c0,6.015-2.132,11.311-6.819,13.002 	c5.397,0.354,7.869,6.277,7.869,14.942C346.255,121.351,341.129,126.295,331.313,126.295"></path> + <path fill="#FF8700" d="M106.074,100.128c-1.247,0.368-2.242,0.506-3.547,0.506c-10.691,0-26.389-37.359-26.389-49.793 	c0-4.577,1.083-6.104,2.613-7.415c-13.084,1.527-28.784,6.329-33.804,12.433c-1.085,1.529-1.745,3.926-1.745,6.98 	c0,19.41,20.718,63.455,35.332,63.455C85.297,126.295,96.696,115.181,106.074,100.128"></path> + <path fill="#FF8700" d="M99.25,42.122c13.52,0,27.049,2.18,27.049,9.812c0,15.483-9.819,34.246-14.832,34.246 	c-8.942,0-20.065-24.867-20.065-37.301C91.403,43.209,93.583,42.122,99.25,42.122"></path> +</svg> diff --git a/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/TYPO3_Logo_Data.svg b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/TYPO3_Logo_Data.svg new file mode 100644 index 000000000000..4e4449894aa2 --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/TYPO3_Logo_Data.svg @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" id="Ebene_1" x="0px" y="0px" width="400px" height="168px" viewBox="0 0 400 168"> + <image></image> + <rect x="0.404" y="0.412" fill="none" width="400" height="168"></rect> + <path d="M164.458,70.495v55.187h-7.691V70.495h-13.622v-6.72h34.934v6.72H164.458z M205.737,96.935v28.747h-7.966V96.935 	l-15.825-33.16h8.485l11.668,25.02l11.676-25.02h8.053L205.737,96.935z M245.705,102.332h-7.429v23.35h-7.698V63.775 	c0,0,7.613-0.625,14.956-0.625c13.438,0,17.331,8.316,17.331,19.195C262.865,95.785,258.261,102.332,245.705,102.332 	 M246.585,69.522c-4.859,0-8.31,0.531-8.31,0.531v25.815h8.31c4.956,0,8.409-3.268,8.409-12.907 	C254.995,74.114,252.863,69.522,246.585,69.522 M290.635,126.295c-14.588,0-18.481-10.61-18.481-32.271 	c0-20.789,3.894-30.873,18.481-30.873c14.587,0,18.478,10.084,18.478,30.873C309.113,115.685,305.222,126.295,290.635,126.295 	 M290.635,69.605c-7.953,0-10.611,5.4-10.611,24.858c0,19.006,2.658,25.383,10.611,25.383s10.61-6.377,10.61-25.383 	C301.246,75.005,298.588,69.605,290.635,69.605 M331.313,126.295c-4.331,0-10.78-1.321-11.587-1.51v-6.444 	c2.129,0.438,7.608,1.349,11.503,1.349c4.501,0,7.428-3.822,7.428-10.64c0-8.039-1.318-12.286-7.601-12.286H323.8v-6.463h6.362 	c7.176,0,7.515-7.34,7.515-10.873c0-6.99-2.202-9.823-6.621-9.823c-3.89,0-8.323,0.973-10.879,1.506v-6.454 	c0.967-0.179,6.193-1.506,10.696-1.506c9.105,0,14.332,3.892,14.332,17.075c0,6.015-2.132,11.311-6.819,13.002 	c5.397,0.354,7.869,6.277,7.869,14.942C346.255,121.351,341.129,126.295,331.313,126.295"></path> + <path fill="#FF8700" d="M106.074,100.128c-1.247,0.368-2.242,0.506-3.547,0.506c-10.691,0-26.389-37.359-26.389-49.793 	c0-4.577,1.083-6.104,2.613-7.415c-13.084,1.527-28.784,6.329-33.804,12.433c-1.085,1.529-1.745,3.926-1.745,6.98 	c0,19.41,20.718,63.455,35.332,63.455C85.297,126.295,96.696,115.181,106.074,100.128"></path> + <path fill="#FF8700" d="M99.25,42.122c13.52,0,27.049,2.18,27.049,9.812c0,15.483-9.819,34.246-14.832,34.246 	c-8.942,0-20.065-24.867-20.065-37.301C91.403,43.209,93.583,42.122,99.25,42.122"></path> +</svg> diff --git a/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/TYPO3_Logo_Script.svg b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/TYPO3_Logo_Script.svg new file mode 100644 index 000000000000..01db9ad346d1 --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/TYPO3_Logo_Script.svg @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" id="Ebene_1" x="0px" y="0px" width="400px" height="168px" viewBox="0 0 400 168"> + <rect x="0.404" y="0.412" fill="none" width="400" height="168"></rect> + <path d="M164.458,70.495v55.187h-7.691V70.495h-13.622v-6.72h34.934v6.72H164.458z M205.737,96.935v28.747h-7.966V96.935 	l-15.825-33.16h8.485l11.668,25.02l11.676-25.02h8.053L205.737,96.935z M245.705,102.332h-7.429v23.35h-7.698V63.775 	c0,0,7.613-0.625,14.956-0.625c13.438,0,17.331,8.316,17.331,19.195C262.865,95.785,258.261,102.332,245.705,102.332 	 M246.585,69.522c-4.859,0-8.31,0.531-8.31,0.531v25.815h8.31c4.956,0,8.409-3.268,8.409-12.907 	C254.995,74.114,252.863,69.522,246.585,69.522 M290.635,126.295c-14.588,0-18.481-10.61-18.481-32.271 	c0-20.789,3.894-30.873,18.481-30.873c14.587,0,18.478,10.084,18.478,30.873C309.113,115.685,305.222,126.295,290.635,126.295 	 M290.635,69.605c-7.953,0-10.611,5.4-10.611,24.858c0,19.006,2.658,25.383,10.611,25.383s10.61-6.377,10.61-25.383 	C301.246,75.005,298.588,69.605,290.635,69.605 M331.313,126.295c-4.331,0-10.78-1.321-11.587-1.51v-6.444 	c2.129,0.438,7.608,1.349,11.503,1.349c4.501,0,7.428-3.822,7.428-10.64c0-8.039-1.318-12.286-7.601-12.286H323.8v-6.463h6.362 	c7.176,0,7.515-7.34,7.515-10.873c0-6.99-2.202-9.823-6.621-9.823c-3.89,0-8.323,0.973-10.879,1.506v-6.454 	c0.967-0.179,6.193-1.506,10.696-1.506c9.105,0,14.332,3.892,14.332,17.075c0,6.015-2.132,11.311-6.819,13.002 	c5.397,0.354,7.869,6.277,7.869,14.942C346.255,121.351,341.129,126.295,331.313,126.295"></path> + <path fill="#FF8700" d="M106.074,100.128c-1.247,0.368-2.242,0.506-3.547,0.506c-10.691,0-26.389-37.359-26.389-49.793 	c0-4.577,1.083-6.104,2.613-7.415c-13.084,1.527-28.784,6.329-33.804,12.433c-1.085,1.529-1.745,3.926-1.745,6.98 	c0,19.41,20.718,63.455,35.332,63.455C85.297,126.295,96.696,115.181,106.074,100.128"></path> + <path fill="#FF8700" d="M99.25,42.122c13.52,0,27.049,2.18,27.049,9.812c0,15.483-9.819,34.246-14.832,34.246 	c-8.942,0-20.065-24.867-20.065-37.301C91.403,43.209,93.583,42.122,99.25,42.122"></path> +</svg> diff --git a/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/ariaData.svg b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/ariaData.svg new file mode 100644 index 000000000000..838e7dc3df9b --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/ariaData.svg @@ -0,0 +1,57 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg version="1" id="cat" viewBox="0 0 720 800" aria-labelledby="catTitle catDesc" role="img"> + <title id="catTitle">Pixels, My Super-friendly Cat</title> + <desc id="catDesc">An illustrated gray cat with bright green blinking eyes.</desc> + <path id="tail" data-name="tail" class="cls-1" d="M545.9,695.9c8,28.2,23.2,42.3,27.2,46.9,21.4,24.1,41.5,40.2,81.1,42.9s65.4-14.2,60.8-26.8-23.1-9.1-51.3-8.3c-35.2.9-66.6-31.3-74.8-63.9s-7.9-63.8-36.8-85.5c-44.1-33-135.6-7.1-159.8-3.4s-48.4,52.5-9.6,45.1,91.4-23.1,123.2-12.7C537.8,640.4,537.9,667.7,545.9,695.9Z" transform="translate(-9.7 -9.3)"></path> + <g id="body"> + <path id="bg" class="cls-2" d="M447.9,502.1c2.1,151.7-108.3,167-216.5,167S9.7,663.8,9.7,510.9,85,242.9,231.3,241,445.8,350.4,447.9,502.1h0Z" transform="translate(-9.7 -9.3)"></path> + <g id="leftleg"> + <path id="leg" class="cls-1" d="M195.6,671.5c-34.2-7.7-40.6-95.6-53.3-191-12-90-90.1-177.2-55.1-177.2s145.7,12,151.4,87.7S261.5,686.5,195.6,671.5Z" transform="translate(-9.7 -9.3)"></path> + <path id="foot" class="cls-3" d="M172.2,688.1c31.6,2.1,56.6-8.7,59.8-32.4s-22.1-49.5-27.3-24.3c25-16.4-39.1-29.4-27.6-3.9,14-24.9-49.6-19.2-31.9-.1-6.5-27.2-35.6,8.2-30.1,29.3C121.5,681.8,140.5,686,172.2,688.1Z" transform="translate(-9.7 -9.3)"></path> + </g> + <g id="rightleg"> + <path id="leg-2" data-name="leg" class="cls-1" d="M260.4,670.4c42.4-9.2,48.7-87.7,53.9-185.2,5.1-96,98.2-176.1,63.1-176.1s-164,15.7-164,111.8C213.4,420.9,199.1,683.7,260.4,670.4Z" transform="translate(-9.7 -9.3)"></path> + <path id="foot-2" data-name="foot" class="cls-3" d="M279.4,689.8c-31.7,2-56.6-9-59.6-32.6s22.3-49.4,27.4-24.1c-24.9-16.5,39.2-29.2,27.6-3.8-13.9-25,49.7-18.9,31.9,0,6.6-27.1,35.6,8.4,30,29.4-6.7,25-25.7,29.1-57.3,31.1h0Z" transform="translate(-9.7 -9.3)"></path> + </g> + <path id="tuft" aria-haspopup="false" class="cls-3" d="M80,331.2c3.5,9.5,1.2,28.9,4.3,32.7s31.5-30,43-20.6c10.7,8.7,1.7,55.9,12.9,64.5,10.1,7.7,32.1-50.6,52.5-38.7,24.9,14.6,34.1,49.9,49,49.9,18.3,0,7.5-49.5,24.1-53.3s46.1,52.6,60.2,45.6c4.8-2.4,3-50.4,12-57.6,8.7-6.9,30.5,22.4,33.5,18.9,3.7-4.1.1-23.1,8.6-36.1,3.4-5.2,18.9-2.6,28.8-.4a3.46,3.46,0,0,0,3.7-5.2c-19.6-30.8-100-147.4-184.2-147.4-93.3,0-150.9,86.8-178.1,141.6a3.43,3.43,0,0,0,3.6,4.9C63,328.4,78.4,326.6,80,331.2Z" transform="translate(-9.7 -9.3)"></path> + </g> + <g id="head"> + <path id="collar" class="cls-4" d="M367,231.1c5.7,36.1-4.7,71-97.8,85.6s-184-18.5-189.7-54.5,16.7-17.3,109.8-31.9,172-35.3,177.7.8" transform="translate(-9.7 -9.3)"></path> + <g id="bg-2" data-name="bg"> + <path class="cls-1" d="M362.5,229.5C339.7,279,273.1,299.4,225,300c-60.6.7-134.7-29.5-153.5-86.4C45.6,135.4,132.2,32.6,225,35.8c96.1,3.4,171.7,119.4,137.5,193.7" transform="translate(-9.7 -9.3)"></path> + <path class="cls-5" d="M362.5,229.5C339.7,279,273.1,299.4,225,300c-60.6.7-134.7-29.5-153.5-86.4C45.6,135.4,132.2,32.6,225,35.8,321.1,39.2,396.7,155.2,362.5,229.5Z" transform="translate(-9.7 -9.3)"></path> + </g> + <g id="leftear" aria-label="Left Ear"> + <path id="outer" class="cls-1" d="M92.7,117c-2.6,4.7-14.7-16.1-16.5-45-3.3-27.7,3.7-63.4,5.4-62C80.7,8,117,10,143,20c27.5,8.9,44.7,25.7,39.5,27.1-30,23.4-59.9,46.6-89.8,69.9" transform="translate(-9.7 -9.3)"></path> + <path id="inner" class="cls-6" d="M105.8,106.9C103.9,110.3,95.3,95.5,94,75c-2.3-19.6,2.6-44.9,3.8-44-0.6-1.4,25.1,0,43.6,7.1,19.5,6.3,31.7,18.2,28,19.2q-31.8,24.9-63.6,49.6" transform="translate(-9.7 -9.3)"></path> + </g> + <path id="mask" class="cls-2" d="M338.4,142.5c-2.2,3.3,19.4,19.6,17.2,23.2s-24.3-7.8-25.8-5.2c-1.9,3.3,33.4,24.1,31,29.2-2.3,4.9-34-14.4-84.3-18.1a141.76,141.76,0,0,1-16.4-2.1,91.21,91.21,0,0,1-13.7-3.9c-19.8-6.9-27.7-10.6-32.7-12-19.3-5.7-26.8,11.3-68.1,22.4-18.8,5-37.9,9.7-54.4,0-2.1-1.3-13.6-8.3-16.7-21.1-0.9-3.6-2.8-15.2,10.5-34C146.3,34.3,216.5,34,217.3,34a131.52,131.52,0,0,1,58.4,14.3c-7.6,4.9-11.2,9.5-9,10.1,21.5,16.5,43.1,33,64.6,49.5,0.9,1.7,3.6-1.3,6.3-7.3,19.3,30.5,22.1,41.5,18.9,44.3-3.8,3.6-16.4-4.8-18.1-2.4" transform="translate(-9.7 -9.3)"></path> + <g id="rightear"> + <path id="outer-2" data-name="outer" class="cls-2" d="M344.9,119.9c2.6,4.7,14.7-16.1,16.5-45,3.3-27.7-3.7-63.4-5.4-62,0.9-2-35.4,0-61.4,10-27.5,8.9-44.7,25.7-39.5,27.1q44.85,35,89.8,69.9" transform="translate(-9.7 -9.3)"></path> + <path id="inner-2" data-name="inner" class="cls-6" d="M343.5,76.2a77.83,77.83,0,0,1-5.6,24.6c-15.1-20.3-36-39.8-61-52.4a82,82,0,0,1,19.2-9.1c18.5-7.1,44.2-8.5,43.6-7.1,1.2-.9,6.1,24.4,3.8,44" transform="translate(-9.7 -9.3)"></path> + </g> + <g id="nose"> + <path class="cls-7" d="M205.1,201.8l-10.6-18.3a9,9,0,0,1,7.7-13.4h21.2a8.9,8.9,0,0,1,7.7,13.4l-10.6,18.3a8.91,8.91,0,0,1-15.4,0" transform="translate(-9.7 -9.3)"></path> + <path class="cls-6" d="M194.2,175.1a9,9,0,0,0,.3,8.4l10.6,18.3a8.92,8.92,0,0,0,15.5,0l8.7-15c-5.8-6.2-19.3-10.1-35.1-11.7" transform="translate(-9.7 -9.3)"></path> + </g> + <g id="mouth"> + <path class="cls-8" d="M166.7,260.4c-24.4,0-44.1-25-44.1-55.9m88.2,0c0,30.9-19.7,55.9-44.1,55.9m89.9,0c24.4,0,44.1-25,44.1-55.9m-88.2,0c0,30.9,19.7,55.9,44.1,55.9" transform="translate(-9.7 -9.3)"></path> + <path class="cls-9" d="M300.7,204.5a65.16,65.16,0,0,1-8,32" transform="translate(-9.7 -9.3)"></path> + </g> + <path id="wiskers" class="cls-10" d="M188.7,198.4c0-12.9-72.7-23.3-162.6-23.3m162.6,36.2c0-7.1-65.8-12.9-147.1-12.9m196,1.3c1.4-12.8,74.8-15.6,164.1-6.2m-165.4,19c0.7-7.1,66.8-5.9,147.6,2.6" transform="translate(-9.7 -9.3)"></path> + <g id="lefteye" class="eye"> + <path id="iris" class="cls-4" d="M188.6,141.5s-18.3,12.3-35.8,7.9-30-15.2-27.7-24c1.5-6,9.6-9.6,20.2-9.8a59.5,59.5,0,0,1,15.7,1.9,35.75,35.75,0,0,1,12.5,6.2,60,60,0,0,1,15.1,17.8" transform="translate(-9.7 -9.3)"></path> + <path class="cls-11" d="M125.1,123.6c1.5-6,9.6-9.6,20.1-9.8a59.5,59.5,0,0,1,15.7,1.9,35.75,35.75,0,0,1,12.5,6.2,59.47,59.47,0,0,1,15.2,17.8" transform="translate(-9.7 -9.3)"></path> + <path id="pupil" class="cls-12" d="M172.9,124.3c-2.3,9.2-10.7,15-18.7,13s-12.5-11.1-10.2-20.4a22.39,22.39,0,0,1,1.1-3.1,59.5,59.5,0,0,1,15.7,1.9,35.75,35.75,0,0,1,12.5,6.2,8.6,8.6,0,0,1-.4,2.4" transform="translate(-9.7 -9.3)"></path> + <path id="eyelash" class="cls-13" d="M124.9,121.5c-7.6,2.6-17.1-4.7-21.1-16.3m33.6,9.5c-7.5,2.9-17.3-4-21.7-15.5m36.7,14.6c-8.1-.1-14.5-10.2-14.3-22.6" transform="translate(-9.7 -9.3)"></path> + <path id="reflection" class="cls-14" d="M156.8,122c0,3.6-2.6,6.4-5.8,6.4s-5.8-2.9-5.8-6.4,2.6-6.4,5.8-6.4,5.8,2.9,5.8,6.4" transform="translate(-9.7 -9.3)"></path> + </g> + <g id="righteye" class="eye"> + <path id="iris-2" data-name="iris" class="cls-4" d="M241.4,143.6s18.5,11.9,36,7.1,29.6-15.8,27.2-24.6c-1.7-6-9.8-9.4-20.3-9.4a59.21,59.21,0,0,0-15.6,2.2,37.44,37.44,0,0,0-12.4,6.4,60.14,60.14,0,0,0-14.9,18.3" transform="translate(-9.7 -9.3)"></path> + <path id="lid" class="cls-11" d="M304.5,124.4c-1.7-6-9.8-9.4-20.3-9.4a59.21,59.21,0,0,0-15.6,2.2,37.44,37.44,0,0,0-12.4,6.4,61.21,61.21,0,0,0-14.9,18.1" transform="translate(-9.7 -9.3)"></path> + <path id="pupil-2" data-name="pupil" class="cls-12" d="M256.7,126.1c2.5,9.2,11,14.8,18.9,12.6s12.3-11.4,9.8-20.6a16.59,16.59,0,0,0-1.2-3.1,59.21,59.21,0,0,0-15.6,2.2,37.44,37.44,0,0,0-12.4,6.4,9.23,9.23,0,0,0,.5,2.5" transform="translate(-9.7 -9.3)"></path> + <path id="eyelash-2" data-name="eyelash" class="cls-13" d="M302.9,122.3c7.7,2.5,17-5,20.8-16.8M292,115.7c7.6,2.8,17.2-4.4,21.4-16M277,115.1c8.1-.3,14.3-10.5,13.9-22.8" transform="translate(-9.7 -9.3)"></path> + <path id="reflection-2" data-name="reflection" class="cls-14" d="M271.1,127.1c0,3.6-2.6,6.5-5.8,6.5s-5.8-2.9-5.8-6.5,2.6-6.4,5.8-6.4,5.8,2.9,5.8,6.4" transform="translate(-9.7 -9.3)"></path> + </g> + </g> +</svg> diff --git a/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/billion_laughs.svg b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/billion_laughs.svg new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/entity.svg b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/entity.svg new file mode 100644 index 000000000000..a7c49b4d49d2 --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/entity.svg @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg xmlns="http://www.w3.org/2000/svg"> + <text x="0" y="20" font-size="20">&lab;</text> +</svg> diff --git a/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/entity_2.svg b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/entity_2.svg new file mode 100644 index 000000000000..cf314616c2ab --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/entity_2.svg @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg xmlns="http://www.w3.org/2000/svg"> + <text x="0" y="20" font-size="20">&lab2;</text> +</svg> diff --git a/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/external.svg b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/external.svg new file mode 100644 index 000000000000..ef4ab4114867 --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/external.svg @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" xml:space="preserve"> +<rect x="0" y="0" width="1000" height="1000"></rect> +<rect x="0" y="0" width="1000" height="1000"></rect> +<rect x="0" y="0" width="1000" height="1000"></rect> +<rect x="0" y="0" width="1000" height="1000"></rect> +<rect x="0" y="0" width="1000" height="1000"></rect> +<rect fill="url('/benis.svg')" x="0" y="0" width="1000" height="1000"></rect> +<rect fill="url('#benis.svg')" x="0" y="0" width="1000" height="1000"></rect> +</svg> diff --git a/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/hrefOne.svg b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/hrefOne.svg new file mode 100644 index 000000000000..b84d2184df75 --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/hrefOne.svg @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" height="600px" id="Layer_1" width="600px" x="0px" y="0px" xml:space="preserve"> + <a>test 1</a> + <a>test 2</a> + <a href="#test3">test 3</a> + <a xlink:href="#test">test 4</a> + + <a>test 5</a> + <a>test 6</a> + + <a>test 7</a> + <a>test 8</a> +</svg> diff --git a/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/hrefTwo.svg b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/hrefTwo.svg new file mode 100644 index 000000000000..2a95507281f2 --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/hrefTwo.svg @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" height="600px" id="Layer_1" width="600px" x="0px" y="0px" xml:space="preserve"> + <a>test 1</a> + <a>test 2</a> + <a href="#test3">test 3</a> + <a xlink:href="#test">test 4</a> + + <a>test 5</a> + <a>test 6</a> + + <a>test 7</a> + <a>test 8</a> +</svg> diff --git a/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/html.svg b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/html.svg new file mode 100644 index 000000000000..c524480099fc --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/html.svg @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg xmlns="http://www.w3.org/2000/svg" version="1.1"> + <rect x="10" y="10" width="100" height="100" stroke="red" stroke-width="10" fill="white"></rect> +</svg> diff --git a/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/simple.svg b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/simple.svg new file mode 100644 index 000000000000..c524480099fc --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/simple.svg @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg xmlns="http://www.w3.org/2000/svg" version="1.1"> + <rect x="10" y="10" width="100" height="100" stroke="red" stroke-width="10" fill="white"></rect> +</svg> diff --git a/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/svgOne.svg b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/svgOne.svg new file mode 100644 index 000000000000..da8faf5f0702 --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/svgOne.svg @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Layer_1" x="0px" y="0px" width="600px" height="600px" viewBox="0 0 600 600" xml:space="preserve"> +<line fill="none" stroke="#000000" stroke-miterlimit="10" x1="119" y1="84.5" x2="454" y2="84.5"></line> +<line fill="none" stroke="#000000" stroke-miterlimit="10" x1="111.212" y1="102.852" x2="112.032" y2="476.623"></line> +<line fill="none" stroke="#000000" stroke-miterlimit="10" x1="198.917" y1="510.229" x2="486.622" y2="501.213"></line> +<line fill="none" stroke="#000000" stroke-miterlimit="10" x1="484.163" y1="442.196" x2="89.901" y2="60.229"></line> +<line fill="none" stroke="#000000" stroke-miterlimit="10" x1="101.376" y1="478.262" x2="443.18" y2="75.803"></line> +<line fill="none" stroke="#000000" stroke-miterlimit="10" x1="457.114" y1="126.623" x2="458.753" y2="363.508"></line> + + +<line fill="none" stroke="#000000" stroke-miterlimit="10" x1="541.54" y1="299.573" x2="543.179" y2="536.458"></line> +</svg> diff --git a/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/use.svg b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/use.svg new file mode 100644 index 000000000000..badd6870ba3c --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/use.svg @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 68 65"> + <use xlink:href="#a" x="28" fill="#1A374D"></use> + <path id="a" d="M14 27v-20c0-3.7-3.3-7-7-7s-7 3.3-7 7v41c0 8.2 9.2 17 20 17s20-9.2 20-20c0-13.3-13.4-21.8-26-18zm6 25c-4 0-7-3-7-7s3-7 7-7 7 3 7 7-3 7-7 7z"></path> + <use></use> +</svg> diff --git a/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/useDos.svg b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/useDos.svg new file mode 100644 index 000000000000..bacbafc2c1fb --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/useDos.svg @@ -0,0 +1,113 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 10 10"> + <defs> + <g id="thing"> + <g id="t0a"></g> + <g id="t0b"></g> + <g id="t1a"></g> + <g id="t1b"></g> + <g id="t2a"></g> + <g id="t2b"></g> + <g id="t3a"></g> + <g id="t3b"></g> + <g id="t4a"></g> + <g id="t4b"></g> + <g id="t5a"></g> + <g id="t5b"></g> + <g id="t6a"></g> + <g id="t6b"></g> + <g id="t7a"></g> + <g id="t7b"></g> + <g id="t8a"></g> + <g id="t8b"></g> + <g id="t9a"></g> + <g id="t9b"></g> + <g id="t10a"></g> + <g id="t10b"></g> + <g id="t11a"></g> + <g id="t11b"></g> + <g id="t12a"></g> + <g id="t12b"></g> + <g id="t13a"></g> + <g id="t13b"></g> + <g id="t14a"></g> + <g id="t14b"></g> + <g id="t15a"></g> + <g id="t15b"></g> + <g id="t16a"></g> + <g id="t16b"></g> + <g id="t17a"></g> + <g id="t17b"></g> + <g id="t18a"></g> + <g id="t18b"></g> + <g id="t19a"></g> + <g id="t19b"></g> + <g id="t20a"></g> + <g id="t20b"></g> + <g id="t21a"></g> + <g id="t21b"></g> + <g id="t22a"></g> + <g id="t22b"></g> + <g id="t23a"></g> + <g id="t23b"></g> + <g id="t24a"></g> + <g id="t24b"></g> + <g id="t25a"></g> + <g id="t25b"></g> + <g id="t26a"></g> + <g id="t26b"></g> + <g id="t27a"></g> + <g id="t27b"></g> + <g id="t28a"></g> + <g id="t28b"></g> + <g id="t29a"></g> + <g id="t29b"></g> + <g id="t30a"></g> + <g id="t30b"></g> + <g id="t31a"></g> + <g id="t31b"></g> + <g id="t32a"></g> + <g id="t32b"></g> + <g id="t33a"></g> + <g id="t33b"></g> + <g id="t34a"></g> + <g id="t34b"></g> + <g id="t35a"></g> + <g id="t35b"></g> + <g id="t36a"></g> + <g id="t36b"></g> + <g id="t37a"></g> + <g id="t37b"></g> + <g id="t38a"></g> + <g id="t38b"></g> + <g id="t39a"></g> + <g id="t39b"></g> + <g id="t40a"></g> + <g id="t40b"></g> + <g id="t41a"></g> + <g id="t41b"></g> + <g id="t42a"></g> + <g id="t42b"></g> + <g id="t43a"></g> + <g id="t43b"></g> + <g id="t44a"></g> + <g id="t44b"></g> + <g id="t45a"></g> + <g id="t45b"></g> + <g id="t46a"></g> + <g id="t46b"></g> + <g id="t47a"></g> + <g id="t47b"></g> + <g id="t48a"></g> + <g id="t48b"></g> + <g id="t49a"></g> + <g id="t49b"></g> + <g id="t50a"> + <circle cx="0" cy="0" r="5"></circle> + </g> + <g id="t50b"> + <circle cx="0" cy="0" r="5"></circle> + </g> + </g> + </defs> +</svg> diff --git a/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/xlinkLaughs.svg b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/xlinkLaughs.svg new file mode 100644 index 000000000000..21661833614a --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/xlinkLaughs.svg @@ -0,0 +1,71 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 512 512" version="1.1" x="0px" y="0px" width="512" height="512"> + <defs> + <g id="a0"> + <circle stroke="#000000" fill="#ffffff" fill-opacity="0.1" r="10"></circle> + </g> + </defs> + <defs> + <g id="a1"> + <use x="0" y="10" xlink:href="#a0"></use> + <use x="10" y="10" xlink:href="#a0"></use> + <use x="20" y="10" xlink:href="#a0"></use> + <use x="30" y="10" xlink:href="#a0"></use> + <use x="40" y="10" xlink:href="#a0"></use> + <use x="50" y="10" xlink:href="#a0"></use> + <use x="60" y="10" xlink:href="#a0"></use> + <use x="70" y="10" xlink:href="#a0"></use> + <use x="80" y="10" xlink:href="#a0"></use> + <use x="90" y="10" xlink:href="#a0"></use> + </g> + </defs> + <defs> + <g id="a2"> + <use x="0" y="10" xlink:href="#a1"></use> + <use x="10" y="10" xlink:href="#a1"></use> + <use x="20" y="10" xlink:href="#a1"></use> + <use x="30" y="10" xlink:href="#a1"></use> + <use x="40" y="10" xlink:href="#a1"></use> + <use x="50" y="10" xlink:href="#a1"></use> + <use x="60" y="10" xlink:href="#a1"></use> + <use x="70" y="10" xlink:href="#a1"></use> + <use x="80" y="10" xlink:href="#a1"></use> + <use x="90" y="10" xlink:href="#a1"></use> + </g> + </defs> + <defs> + <g id="a3"> + <use x="0" y="10" xlink:href="#a2"></use> + <use x="10" y="10" xlink:href="#a2"></use> + <use x="20" y="10" xlink:href="#a2"></use> + <use x="30" y="10" xlink:href="#a2"></use> + <use x="40" y="10" xlink:href="#a2"></use> + <use x="50" y="10" xlink:href="#a2"></use> + <use x="60" y="10" xlink:href="#a2"></use> + <use x="70" y="10" xlink:href="#a2"></use> + <use x="80" y="10" xlink:href="#a2"></use> + <use x="90" y="10" xlink:href="#a2"></use> + </g> + </defs> + <defs> + <g id="a4"></g> + </defs> + <defs> + <g id="a5"></g> + </defs> + <defs> + <g id="a6"></g> + </defs> + <defs> + <g id="a7"></g> + </defs> + <defs> + <g id="a8"></g> + </defs> + <defs> + <g id="a9"></g> + </defs> + <defs> + <g id="a10"></g> + </defs> +</svg> diff --git a/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/xlinkLoop.svg b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/xlinkLoop.svg new file mode 100644 index 000000000000..c6dd6bdaff67 --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/xlinkLoop.svg @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 500 500"> + <!-- ping:pong section to be removed --> + <g id="ping"> + <text style="font-weight: 700;" x="50" y="50">Ping</text> + </g> + <g id="pong"> + <text x="50" y="100" style="font-weight: 700">Pong</text> + </g> + <!-- nested loop --> + <g id="first"> + <text style="font-weight: 700;" x="50" y="50">1st</text> + </g> + <g id="second"> + <text style="font-weight: 700;" x="50" y="50">2nd</text> + </g> + <g id="third"> + <text style="font-weight: 700;" x="50" y="50">3rd</text> + </g> + <g id="fourth"> + <text style="font-weight: 700;" x="50" y="50">4th</text> + </g> + <!-- self reference to be removed --> +</svg> diff --git a/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/xlink_laughs.svg b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/xlink_laughs.svg new file mode 100644 index 000000000000..ae53de9ab717 --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/xlink_laughs.svg @@ -0,0 +1,146 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 512 512" version="1.1" xml:space="preserve" x="0px" y="0px" width="512" height="512"> + <defs> + <g id="a0"> + <circle stroke="#000000" fill="#ffffff" fill-opacity="0.1" r="10"></circle> + </g> + </defs><defs> +<g id="a1"> +<use x="0" y="10" xlink:href="#a0"></use> +<use x="10" y="10" xlink:href="#a0"></use> +<use x="20" y="10" xlink:href="#a0"></use> +<use x="30" y="10" xlink:href="#a0"></use> +<use x="40" y="10" xlink:href="#a0"></use> +<use x="50" y="10" xlink:href="#a0"></use> +<use x="60" y="10" xlink:href="#a0"></use> +<use x="70" y="10" xlink:href="#a0"></use> +<use x="80" y="10" xlink:href="#a0"></use> +<use x="90" y="10" xlink:href="#a0"></use> +</g> +</defs> +<defs> +<g id="a2"> +<use x="0" y="10" xlink:href="#a1"></use> +<use x="10" y="10" xlink:href="#a1"></use> +<use x="20" y="10" xlink:href="#a1"></use> +<use x="30" y="10" xlink:href="#a1"></use> +<use x="40" y="10" xlink:href="#a1"></use> +<use x="50" y="10" xlink:href="#a1"></use> +<use x="60" y="10" xlink:href="#a1"></use> +<use x="70" y="10" xlink:href="#a1"></use> +<use x="80" y="10" xlink:href="#a1"></use> +<use x="90" y="10" xlink:href="#a1"></use> +</g> +</defs> +<defs> +<g id="a3"> +<use x="0" y="10" xlink:href="#a2"></use> +<use x="10" y="10" xlink:href="#a2"></use> +<use x="20" y="10" xlink:href="#a2"></use> +<use x="30" y="10" xlink:href="#a2"></use> +<use x="40" y="10" xlink:href="#a2"></use> +<use x="50" y="10" xlink:href="#a2"></use> +<use x="60" y="10" xlink:href="#a2"></use> +<use x="70" y="10" xlink:href="#a2"></use> +<use x="80" y="10" xlink:href="#a2"></use> +<use x="90" y="10" xlink:href="#a2"></use> +</g> +</defs> +<defs> +<g id="a4"> + + + + + + + + + + +</g> +</defs> +<defs> +<g id="a5"> + + + + + + + + + + +</g> +</defs> +<defs> +<g id="a6"> + + + + + + + + + + +</g> +</defs> +<defs> +<g id="a7"> + + + + + + + + + + +</g> +</defs> +<defs> +<g id="a8"> + + + + + + + + + + +</g> +</defs> +<defs> +<g id="a9"> + + + + + + + + + + +</g> +</defs> +<defs> +<g id="a10"> + + + + + + + + + + +</g> +</defs></svg> diff --git a/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/xmlOne.xml b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/xmlOne.xml new file mode 100644 index 000000000000..eddcb7b55586 --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/xmlOne.xml @@ -0,0 +1,11 @@ +<svg xmlns="http://www.w3.org/2000/svg"> + <image/> + <svg/> + + <defs/> + <g> + <circle/> + <text/> + </g> + +</svg> \ No newline at end of file diff --git a/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/xss.svg b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/xss.svg new file mode 100644 index 000000000000..7e8106f2285b --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/CleanSVG/xss.svg @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg xmlns="http://www.w3.org/2000/svg" version="1.1"> + <rect x="100" y="100" width="100" height="100" stroke="red" stroke-width="10" fill="white"></rect> +</svg> diff --git a/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/TYPO3_Logo_Clean.svg b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/TYPO3_Logo_Clean.svg new file mode 100644 index 000000000000..01db9ad346d1 --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/TYPO3_Logo_Clean.svg @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" id="Ebene_1" x="0px" y="0px" width="400px" height="168px" viewBox="0 0 400 168"> + <rect x="0.404" y="0.412" fill="none" width="400" height="168"></rect> + <path d="M164.458,70.495v55.187h-7.691V70.495h-13.622v-6.72h34.934v6.72H164.458z M205.737,96.935v28.747h-7.966V96.935 	l-15.825-33.16h8.485l11.668,25.02l11.676-25.02h8.053L205.737,96.935z M245.705,102.332h-7.429v23.35h-7.698V63.775 	c0,0,7.613-0.625,14.956-0.625c13.438,0,17.331,8.316,17.331,19.195C262.865,95.785,258.261,102.332,245.705,102.332 	 M246.585,69.522c-4.859,0-8.31,0.531-8.31,0.531v25.815h8.31c4.956,0,8.409-3.268,8.409-12.907 	C254.995,74.114,252.863,69.522,246.585,69.522 M290.635,126.295c-14.588,0-18.481-10.61-18.481-32.271 	c0-20.789,3.894-30.873,18.481-30.873c14.587,0,18.478,10.084,18.478,30.873C309.113,115.685,305.222,126.295,290.635,126.295 	 M290.635,69.605c-7.953,0-10.611,5.4-10.611,24.858c0,19.006,2.658,25.383,10.611,25.383s10.61-6.377,10.61-25.383 	C301.246,75.005,298.588,69.605,290.635,69.605 M331.313,126.295c-4.331,0-10.78-1.321-11.587-1.51v-6.444 	c2.129,0.438,7.608,1.349,11.503,1.349c4.501,0,7.428-3.822,7.428-10.64c0-8.039-1.318-12.286-7.601-12.286H323.8v-6.463h6.362 	c7.176,0,7.515-7.34,7.515-10.873c0-6.99-2.202-9.823-6.621-9.823c-3.89,0-8.323,0.973-10.879,1.506v-6.454 	c0.967-0.179,6.193-1.506,10.696-1.506c9.105,0,14.332,3.892,14.332,17.075c0,6.015-2.132,11.311-6.819,13.002 	c5.397,0.354,7.869,6.277,7.869,14.942C346.255,121.351,341.129,126.295,331.313,126.295"></path> + <path fill="#FF8700" d="M106.074,100.128c-1.247,0.368-2.242,0.506-3.547,0.506c-10.691,0-26.389-37.359-26.389-49.793 	c0-4.577,1.083-6.104,2.613-7.415c-13.084,1.527-28.784,6.329-33.804,12.433c-1.085,1.529-1.745,3.926-1.745,6.98 	c0,19.41,20.718,63.455,35.332,63.455C85.297,126.295,96.696,115.181,106.074,100.128"></path> + <path fill="#FF8700" d="M99.25,42.122c13.52,0,27.049,2.18,27.049,9.812c0,15.483-9.819,34.246-14.832,34.246 	c-8.942,0-20.065-24.867-20.065-37.301C91.403,43.209,93.583,42.122,99.25,42.122"></path> +</svg> diff --git a/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/TYPO3_Logo_Data.svg b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/TYPO3_Logo_Data.svg new file mode 100644 index 000000000000..0a014746b779 --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/TYPO3_Logo_Data.svg @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" id="Ebene_1" x="0px" y="0px" width="400px" height="168px" viewBox="0 0 400 168"> + <image data="foo" /> + <rect x="0.404" y="0.412" fill="none" width="400" height="168"></rect> + <path d="M164.458,70.495v55.187h-7.691V70.495h-13.622v-6.72h34.934v6.72H164.458z M205.737,96.935v28.747h-7.966V96.935 	l-15.825-33.16h8.485l11.668,25.02l11.676-25.02h8.053L205.737,96.935z M245.705,102.332h-7.429v23.35h-7.698V63.775 	c0,0,7.613-0.625,14.956-0.625c13.438,0,17.331,8.316,17.331,19.195C262.865,95.785,258.261,102.332,245.705,102.332 	 M246.585,69.522c-4.859,0-8.31,0.531-8.31,0.531v25.815h8.31c4.956,0,8.409-3.268,8.409-12.907 	C254.995,74.114,252.863,69.522,246.585,69.522 M290.635,126.295c-14.588,0-18.481-10.61-18.481-32.271 	c0-20.789,3.894-30.873,18.481-30.873c14.587,0,18.478,10.084,18.478,30.873C309.113,115.685,305.222,126.295,290.635,126.295 	 M290.635,69.605c-7.953,0-10.611,5.4-10.611,24.858c0,19.006,2.658,25.383,10.611,25.383s10.61-6.377,10.61-25.383 	C301.246,75.005,298.588,69.605,290.635,69.605 M331.313,126.295c-4.331,0-10.78-1.321-11.587-1.51v-6.444 	c2.129,0.438,7.608,1.349,11.503,1.349c4.501,0,7.428-3.822,7.428-10.64c0-8.039-1.318-12.286-7.601-12.286H323.8v-6.463h6.362 	c7.176,0,7.515-7.34,7.515-10.873c0-6.99-2.202-9.823-6.621-9.823c-3.89,0-8.323,0.973-10.879,1.506v-6.454 	c0.967-0.179,6.193-1.506,10.696-1.506c9.105,0,14.332,3.892,14.332,17.075c0,6.015-2.132,11.311-6.819,13.002 	c5.397,0.354,7.869,6.277,7.869,14.942C346.255,121.351,341.129,126.295,331.313,126.295"></path> + <path fill="#FF8700" d="M106.074,100.128c-1.247,0.368-2.242,0.506-3.547,0.506c-10.691,0-26.389-37.359-26.389-49.793 	c0-4.577,1.083-6.104,2.613-7.415c-13.084,1.527-28.784,6.329-33.804,12.433c-1.085,1.529-1.745,3.926-1.745,6.98 	c0,19.41,20.718,63.455,35.332,63.455C85.297,126.295,96.696,115.181,106.074,100.128"></path> + <path fill="#FF8700" d="M99.25,42.122c13.52,0,27.049,2.18,27.049,9.812c0,15.483-9.819,34.246-14.832,34.246 	c-8.942,0-20.065-24.867-20.065-37.301C91.403,43.209,93.583,42.122,99.25,42.122"></path> +</svg> diff --git a/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/TYPO3_Logo_Script.svg b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/TYPO3_Logo_Script.svg new file mode 100644 index 000000000000..e1170d4f674d --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/TYPO3_Logo_Script.svg @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" id="Ebene_1" x="0px" y="0px" width="400px" height="168px" viewBox="0 0 400 168"> + <script type="text/javascript"> + // <![CDATA[ + function doBadThings(evt) { + } + // ]]> + </script> + <rect x="0.404" y="0.412" fill="none" width="400" height="168"></rect> + <path d="M164.458,70.495v55.187h-7.691V70.495h-13.622v-6.72h34.934v6.72H164.458z M205.737,96.935v28.747h-7.966V96.935 	l-15.825-33.16h8.485l11.668,25.02l11.676-25.02h8.053L205.737,96.935z M245.705,102.332h-7.429v23.35h-7.698V63.775 	c0,0,7.613-0.625,14.956-0.625c13.438,0,17.331,8.316,17.331,19.195C262.865,95.785,258.261,102.332,245.705,102.332 	 M246.585,69.522c-4.859,0-8.31,0.531-8.31,0.531v25.815h8.31c4.956,0,8.409-3.268,8.409-12.907 	C254.995,74.114,252.863,69.522,246.585,69.522 M290.635,126.295c-14.588,0-18.481-10.61-18.481-32.271 	c0-20.789,3.894-30.873,18.481-30.873c14.587,0,18.478,10.084,18.478,30.873C309.113,115.685,305.222,126.295,290.635,126.295 	 M290.635,69.605c-7.953,0-10.611,5.4-10.611,24.858c0,19.006,2.658,25.383,10.611,25.383s10.61-6.377,10.61-25.383 	C301.246,75.005,298.588,69.605,290.635,69.605 M331.313,126.295c-4.331,0-10.78-1.321-11.587-1.51v-6.444 	c2.129,0.438,7.608,1.349,11.503,1.349c4.501,0,7.428-3.822,7.428-10.64c0-8.039-1.318-12.286-7.601-12.286H323.8v-6.463h6.362 	c7.176,0,7.515-7.34,7.515-10.873c0-6.99-2.202-9.823-6.621-9.823c-3.89,0-8.323,0.973-10.879,1.506v-6.454 	c0.967-0.179,6.193-1.506,10.696-1.506c9.105,0,14.332,3.892,14.332,17.075c0,6.015-2.132,11.311-6.819,13.002 	c5.397,0.354,7.869,6.277,7.869,14.942C346.255,121.351,341.129,126.295,331.313,126.295"></path> + <path fill="#FF8700" d="M106.074,100.128c-1.247,0.368-2.242,0.506-3.547,0.506c-10.691,0-26.389-37.359-26.389-49.793 	c0-4.577,1.083-6.104,2.613-7.415c-13.084,1.527-28.784,6.329-33.804,12.433c-1.085,1.529-1.745,3.926-1.745,6.98 	c0,19.41,20.718,63.455,35.332,63.455C85.297,126.295,96.696,115.181,106.074,100.128"></path> + <path fill="#FF8700" d="M99.25,42.122c13.52,0,27.049,2.18,27.049,9.812c0,15.483-9.819,34.246-14.832,34.246 	c-8.942,0-20.065-24.867-20.065-37.301C91.403,43.209,93.583,42.122,99.25,42.122"></path> +</svg> diff --git a/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/ariaData.svg b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/ariaData.svg new file mode 100644 index 000000000000..d09ea5d95413 --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/ariaData.svg @@ -0,0 +1,56 @@ +<svg version="1" id="cat" viewBox="0 0 720 800" aria-labelledby="catTitle catDesc" role="img"> + <title id="catTitle" arial-dontallow="nope">Pixels, My Super-friendly Cat</title> + <desc id="catDesc">An illustrated gray cat with bright green blinking eyes.</desc> + <path id="tail" data-name="tail" class="cls-1" d="M545.9,695.9c8,28.2,23.2,42.3,27.2,46.9,21.4,24.1,41.5,40.2,81.1,42.9s65.4-14.2,60.8-26.8-23.1-9.1-51.3-8.3c-35.2.9-66.6-31.3-74.8-63.9s-7.9-63.8-36.8-85.5c-44.1-33-135.6-7.1-159.8-3.4s-48.4,52.5-9.6,45.1,91.4-23.1,123.2-12.7C537.8,640.4,537.9,667.7,545.9,695.9Z" transform="translate(-9.7 -9.3)"/> + <g id="body"> + <path id="bg" class="cls-2" d="M447.9,502.1c2.1,151.7-108.3,167-216.5,167S9.7,663.8,9.7,510.9,85,242.9,231.3,241,445.8,350.4,447.9,502.1h0Z" transform="translate(-9.7 -9.3)"/> + <g id="leftleg" datas-dontallow="nope"> + <path id="leg" class="cls-1" d="M195.6,671.5c-34.2-7.7-40.6-95.6-53.3-191-12-90-90.1-177.2-55.1-177.2s145.7,12,151.4,87.7S261.5,686.5,195.6,671.5Z" transform="translate(-9.7 -9.3)"/> + <path id="foot" class="cls-3" d="M172.2,688.1c31.6,2.1,56.6-8.7,59.8-32.4s-22.1-49.5-27.3-24.3c25-16.4-39.1-29.4-27.6-3.9,14-24.9-49.6-19.2-31.9-.1-6.5-27.2-35.6,8.2-30.1,29.3C121.5,681.8,140.5,686,172.2,688.1Z" transform="translate(-9.7 -9.3)"/> + </g> + <g id="rightleg"> + <path id="leg-2" data-name="leg" class="cls-1" d="M260.4,670.4c42.4-9.2,48.7-87.7,53.9-185.2,5.1-96,98.2-176.1,63.1-176.1s-164,15.7-164,111.8C213.4,420.9,199.1,683.7,260.4,670.4Z" transform="translate(-9.7 -9.3)"/> + <path id="foot-2" data-name="foot" class="cls-3" d="M279.4,689.8c-31.7,2-56.6-9-59.6-32.6s22.3-49.4,27.4-24.1c-24.9-16.5,39.2-29.2,27.6-3.8-13.9-25,49.7-18.9,31.9,0,6.6-27.1,35.6,8.4,30,29.4-6.7,25-25.7,29.1-57.3,31.1h0Z" transform="translate(-9.7 -9.3)"/> + </g> + <path id="tuft" aria-haspopup="false" class="cls-3" d="M80,331.2c3.5,9.5,1.2,28.9,4.3,32.7s31.5-30,43-20.6c10.7,8.7,1.7,55.9,12.9,64.5,10.1,7.7,32.1-50.6,52.5-38.7,24.9,14.6,34.1,49.9,49,49.9,18.3,0,7.5-49.5,24.1-53.3s46.1,52.6,60.2,45.6c4.8-2.4,3-50.4,12-57.6,8.7-6.9,30.5,22.4,33.5,18.9,3.7-4.1.1-23.1,8.6-36.1,3.4-5.2,18.9-2.6,28.8-.4a3.46,3.46,0,0,0,3.7-5.2c-19.6-30.8-100-147.4-184.2-147.4-93.3,0-150.9,86.8-178.1,141.6a3.43,3.43,0,0,0,3.6,4.9C63,328.4,78.4,326.6,80,331.2Z" transform="translate(-9.7 -9.3)"/> + </g> + <g id="head"> + <path id="collar" class="cls-4" d="M367,231.1c5.7,36.1-4.7,71-97.8,85.6s-184-18.5-189.7-54.5,16.7-17.3,109.8-31.9,172-35.3,177.7.8" transform="translate(-9.7 -9.3)"/> + <g id="bg-2" data-name="bg"> + <path class="cls-1" d="M362.5,229.5C339.7,279,273.1,299.4,225,300c-60.6.7-134.7-29.5-153.5-86.4C45.6,135.4,132.2,32.6,225,35.8c96.1,3.4,171.7,119.4,137.5,193.7" transform="translate(-9.7 -9.3)"/> + <path class="cls-5" d="M362.5,229.5C339.7,279,273.1,299.4,225,300c-60.6.7-134.7-29.5-153.5-86.4C45.6,135.4,132.2,32.6,225,35.8,321.1,39.2,396.7,155.2,362.5,229.5Z" transform="translate(-9.7 -9.3)"/> + </g> + <g id="leftear" aria-label="Left Ear"> + <path id="outer" class="cls-1" d="M92.7,117c-2.6,4.7-14.7-16.1-16.5-45-3.3-27.7,3.7-63.4,5.4-62C80.7,8,117,10,143,20c27.5,8.9,44.7,25.7,39.5,27.1-30,23.4-59.9,46.6-89.8,69.9" transform="translate(-9.7 -9.3)"/> + <path id="inner" class="cls-6" d="M105.8,106.9C103.9,110.3,95.3,95.5,94,75c-2.3-19.6,2.6-44.9,3.8-44-0.6-1.4,25.1,0,43.6,7.1,19.5,6.3,31.7,18.2,28,19.2q-31.8,24.9-63.6,49.6" transform="translate(-9.7 -9.3)"/> + </g> + <path id="mask" class="cls-2" d="M338.4,142.5c-2.2,3.3,19.4,19.6,17.2,23.2s-24.3-7.8-25.8-5.2c-1.9,3.3,33.4,24.1,31,29.2-2.3,4.9-34-14.4-84.3-18.1a141.76,141.76,0,0,1-16.4-2.1,91.21,91.21,0,0,1-13.7-3.9c-19.8-6.9-27.7-10.6-32.7-12-19.3-5.7-26.8,11.3-68.1,22.4-18.8,5-37.9,9.7-54.4,0-2.1-1.3-13.6-8.3-16.7-21.1-0.9-3.6-2.8-15.2,10.5-34C146.3,34.3,216.5,34,217.3,34a131.52,131.52,0,0,1,58.4,14.3c-7.6,4.9-11.2,9.5-9,10.1,21.5,16.5,43.1,33,64.6,49.5,0.9,1.7,3.6-1.3,6.3-7.3,19.3,30.5,22.1,41.5,18.9,44.3-3.8,3.6-16.4-4.8-18.1-2.4" transform="translate(-9.7 -9.3)"/> + <g id="rightear"> + <path id="outer-2" data-name="outer" class="cls-2" d="M344.9,119.9c2.6,4.7,14.7-16.1,16.5-45,3.3-27.7-3.7-63.4-5.4-62,0.9-2-35.4,0-61.4,10-27.5,8.9-44.7,25.7-39.5,27.1q44.85,35,89.8,69.9" transform="translate(-9.7 -9.3)"/> + <path id="inner-2" data-name="inner" class="cls-6" d="M343.5,76.2a77.83,77.83,0,0,1-5.6,24.6c-15.1-20.3-36-39.8-61-52.4a82,82,0,0,1,19.2-9.1c18.5-7.1,44.2-8.5,43.6-7.1,1.2-.9,6.1,24.4,3.8,44" transform="translate(-9.7 -9.3)"/> + </g> + <g id="nose"> + <path class="cls-7" d="M205.1,201.8l-10.6-18.3a9,9,0,0,1,7.7-13.4h21.2a8.9,8.9,0,0,1,7.7,13.4l-10.6,18.3a8.91,8.91,0,0,1-15.4,0" transform="translate(-9.7 -9.3)"/> + <path class="cls-6" d="M194.2,175.1a9,9,0,0,0,.3,8.4l10.6,18.3a8.92,8.92,0,0,0,15.5,0l8.7-15c-5.8-6.2-19.3-10.1-35.1-11.7" transform="translate(-9.7 -9.3)"/> + </g> + <g id="mouth"> + <path class="cls-8" d="M166.7,260.4c-24.4,0-44.1-25-44.1-55.9m88.2,0c0,30.9-19.7,55.9-44.1,55.9m89.9,0c24.4,0,44.1-25,44.1-55.9m-88.2,0c0,30.9,19.7,55.9,44.1,55.9" transform="translate(-9.7 -9.3)"/> + <path class="cls-9" d="M300.7,204.5a65.16,65.16,0,0,1-8,32" transform="translate(-9.7 -9.3)"/> + </g> + <path id="wiskers" class="cls-10" d="M188.7,198.4c0-12.9-72.7-23.3-162.6-23.3m162.6,36.2c0-7.1-65.8-12.9-147.1-12.9m196,1.3c1.4-12.8,74.8-15.6,164.1-6.2m-165.4,19c0.7-7.1,66.8-5.9,147.6,2.6" transform="translate(-9.7 -9.3)"/> + <g id="lefteye" class="eye"> + <path id="iris" class="cls-4" d="M188.6,141.5s-18.3,12.3-35.8,7.9-30-15.2-27.7-24c1.5-6,9.6-9.6,20.2-9.8a59.5,59.5,0,0,1,15.7,1.9,35.75,35.75,0,0,1,12.5,6.2,60,60,0,0,1,15.1,17.8" transform="translate(-9.7 -9.3)"/> + <path class="cls-11" d="M125.1,123.6c1.5-6,9.6-9.6,20.1-9.8a59.5,59.5,0,0,1,15.7,1.9,35.75,35.75,0,0,1,12.5,6.2,59.47,59.47,0,0,1,15.2,17.8" transform="translate(-9.7 -9.3)"/> + <path id="pupil" class="cls-12" d="M172.9,124.3c-2.3,9.2-10.7,15-18.7,13s-12.5-11.1-10.2-20.4a22.39,22.39,0,0,1,1.1-3.1,59.5,59.5,0,0,1,15.7,1.9,35.75,35.75,0,0,1,12.5,6.2,8.6,8.6,0,0,1-.4,2.4" transform="translate(-9.7 -9.3)"/> + <path id="eyelash" class="cls-13" d="M124.9,121.5c-7.6,2.6-17.1-4.7-21.1-16.3m33.6,9.5c-7.5,2.9-17.3-4-21.7-15.5m36.7,14.6c-8.1-.1-14.5-10.2-14.3-22.6" transform="translate(-9.7 -9.3)"/> + <path id="reflection" class="cls-14" d="M156.8,122c0,3.6-2.6,6.4-5.8,6.4s-5.8-2.9-5.8-6.4,2.6-6.4,5.8-6.4,5.8,2.9,5.8,6.4" transform="translate(-9.7 -9.3)"/> + </g> + <g id="righteye" class="eye"> + <path id="iris-2" data-name="iris" class="cls-4" d="M241.4,143.6s18.5,11.9,36,7.1,29.6-15.8,27.2-24.6c-1.7-6-9.8-9.4-20.3-9.4a59.21,59.21,0,0,0-15.6,2.2,37.44,37.44,0,0,0-12.4,6.4,60.14,60.14,0,0,0-14.9,18.3" transform="translate(-9.7 -9.3)"/> + <path id="lid" class="cls-11" d="M304.5,124.4c-1.7-6-9.8-9.4-20.3-9.4a59.21,59.21,0,0,0-15.6,2.2,37.44,37.44,0,0,0-12.4,6.4,61.21,61.21,0,0,0-14.9,18.1" transform="translate(-9.7 -9.3)"/> + <path id="pupil-2" data-name="pupil" class="cls-12" d="M256.7,126.1c2.5,9.2,11,14.8,18.9,12.6s12.3-11.4,9.8-20.6a16.59,16.59,0,0,0-1.2-3.1,59.21,59.21,0,0,0-15.6,2.2,37.44,37.44,0,0,0-12.4,6.4,9.23,9.23,0,0,0,.5,2.5" transform="translate(-9.7 -9.3)"/> + <path id="eyelash-2" data-name="eyelash" class="cls-13" d="M302.9,122.3c7.7,2.5,17-5,20.8-16.8M292,115.7c7.6,2.8,17.2-4.4,21.4-16M277,115.1c8.1-.3,14.3-10.5,13.9-22.8" transform="translate(-9.7 -9.3)"/> + <path id="reflection-2" data-name="reflection" class="cls-14" d="M271.1,127.1c0,3.6-2.6,6.5-5.8,6.5s-5.8-2.9-5.8-6.5,2.6-6.4,5.8-6.4,5.8,2.9,5.8,6.4" transform="translate(-9.7 -9.3)"/> + </g> + </g> +</svg> \ No newline at end of file diff --git a/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/billion_laughs.svg b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/billion_laughs.svg new file mode 100644 index 000000000000..dc9414089ff9 --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/billion_laughs.svg @@ -0,0 +1,16 @@ +<?xml version="1.0" standalone="no"?> +<!DOCTYPE lolz [ +<!ENTITY lol "lol"> +<!ENTITY lol2 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;"> +<!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;"> +<!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;"> +<!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;"> +<!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;"> +<!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;"> +<!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;"> +<!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;"> +<!ENTITY lol10 "&lol9;&lol9;&lol9;&lol9;&lol9;&lol9;&lol9;&lol9;&lol9;&lol9;"> +]> +<svg xmlns="http://www.w3.org/2000/svg"> + <text x="0" y="20" font-size="20">&lol10;</text> +</svg> \ No newline at end of file diff --git a/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/entity.svg b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/entity.svg new file mode 100644 index 000000000000..bc2d3defac21 --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/entity.svg @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE fortiguard [ <!ENTITY lab "cool, text as an image">]> +<svg xmlns="http://www.w3.org/2000/svg"> + <text x="0" y="20" font-size="20">&lab;</text> +</svg> \ No newline at end of file diff --git a/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/entity_2.svg b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/entity_2.svg new file mode 100644 index 000000000000..19d3a5b057eb --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/entity_2.svg @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE fortiguard [ +<!ENTITY lab "cool, text as an image"> +<!ENTITY lab2 "&lab;&lab;"> +]> +<svg xmlns="http://www.w3.org/2000/svg"> + <text x="0" y="20" font-size="20">&lab2;</text> +</svg> \ No newline at end of file diff --git a/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/external.svg b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/external.svg new file mode 100644 index 000000000000..cd190cb20038 --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/external.svg @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve"> +<rect fill="url('http://example.com/benis.svg')" x="0" y="0" width="1000" height="1000"></rect> +<rect fill="url('https://example.com/benis.svg')" x="0" y="0" width="1000" height="1000"></rect> +<rect fill=" url( ' https://example.com/benis.svg ' ) " x="0" y="0" width="1000" height="1000"></rect> +<rect fill="url('ftp://192.168.2.1/benis.svg')" x="0" y="0" width="1000" height="1000"></rect> +<rect fill="url('//example.com/benis.svg')" x="0" y="0" width="1000" height="1000"></rect> +<rect fill="url('/benis.svg')" x="0" y="0" width="1000" height="1000"></rect> +<rect fill="url('#benis.svg')" x="0" y="0" width="1000" height="1000"></rect> +</svg> diff --git a/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/hrefOne.svg b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/hrefOne.svg new file mode 100644 index 000000000000..4f26966a17e5 --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/hrefOne.svg @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" height="600px" id="Layer_1" width="600px" x="0px" y="0px" xml:space="preserve"> + <a href="javascript:alert(2)">test 1</a> + <a xlink:href="javascript:alert(2)">test 2</a> + <a href="#test3">test 3</a> + <a xlink:href="#test">test 4</a> + + <a href="data:data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' onload='alert(88)'%3E%3C/svg%3E">test 5</a> + <a xlink:href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' onload='alert(88)'%3E%3C/svg%3E">test 6</a> + + <a href="javascript	:alert(document.domain)">test 7</a> + <a href="javascrip	t:alert('0xd0ff9')">test 8</a> +</svg> diff --git a/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/hrefTwo.svg b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/hrefTwo.svg new file mode 100644 index 000000000000..3e7be42d7cf3 --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/hrefTwo.svg @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" height="600px" id="Layer_1" width="600px" x="0px" y="0px" xml:space="preserve"> + <a href="javascript:alert(2)">test 1</a> + <a xlink:href="javascript:alert(2)">test 2</a> + <a href="#test3">test 3</a> + <a xlink:href="#test">test 4</a> + + <a href="data:data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' onload='alert(88)'%3E%3C/svg%3E">test 5</a> + <a xlink:href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' onload='alert(88)'%3E%3C/svg%3E">test 6</a> + + <a href="javascript	:alert(document.domain)">test 7</a> + <a href="javascrip	t:alert('0xd0ff9')">test 8</a> +</svg> diff --git a/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/html.svg b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/html.svg new file mode 100644 index 000000000000..31bd3590ce8d --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/html.svg @@ -0,0 +1,14 @@ +<?xml version="1.0" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" > + <rect x="10" y="10" width="100" height="100" stroke="red" stroke-width="10" fill="white" /> + <foreignObject class="node" x="46" y="22" width="200" height="300"> + <body xmlns="http://www.w3.org/1999/xhtml"> + <style> + h1 {color: blue} + </style> + <h1>HTML Injection for phishing</h1> + </body> + </foreignObject> +</svg> + diff --git a/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/simple.svg b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/simple.svg new file mode 100644 index 000000000000..29fc853c7715 --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/simple.svg @@ -0,0 +1,5 @@ +<?xml version="1.0" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg"> + <rect x="10" y="10" width="100" height="100" stroke="red" stroke-width="10" fill="white" /> +</svg> \ No newline at end of file diff --git a/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/svgOne.svg b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/svgOne.svg new file mode 100644 index 000000000000..f543a84b5f32 --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/svgOne.svg @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + width="600px" height="600px" viewBox="0 0 600 600" enable-background="new 0 0 600 600" xml:space="preserve"> +<line onload="alert(2)" fill="none" stroke="#000000" stroke-miterlimit="10" x1="119" y1="84.5" x2="454" y2="84.5"/> +<line fill="none" stroke="#000000" stroke-miterlimit="10" x1="111.212" y1="102.852" x2="112.032" y2="476.623"/> +<line fill="none" stroke="#000000" stroke-miterlimit="10" x1="198.917" y1="510.229" x2="486.622" y2="501.213"/> +<line fill="none" stroke="#000000" stroke-miterlimit="10" x1="484.163" y1="442.196" x2="89.901" y2="60.229"/> +<line fill="none" stroke="#000000" stroke-miterlimit="10" x1="101.376" y1="478.262" x2="443.18" y2="75.803"/> +<line fill="none" stroke="#000000" stroke-miterlimit="10" x1="457.114" y1="126.623" x2="458.753" y2="363.508"/> +<this>shouldn't be here</this> +<script>alert(1);</script> +<line fill="none" stroke="#000000" stroke-miterlimit="10" x1="541.54" y1="299.573" x2="543.179" y2="536.458"/> +</svg> diff --git a/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/use.svg b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/use.svg new file mode 100644 index 000000000000..888416a20809 --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/use.svg @@ -0,0 +1,5 @@ +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 68 65"> + <use xlink:href="#a" x="28" fill="#1A374D"/> + <path id="a" d="M14 27v-20c0-3.7-3.3-7-7-7s-7 3.3-7 7v41c0 8.2 9.2 17 20 17s20-9.2 20-20c0-13.3-13.4-21.8-26-18zm6 25c-4 0-7-3-7-7s3-7 7-7 7 3 7 7-3 7-7 7z"/> + <use xlink:href="defs.svg#icon-1"/> +</svg> \ No newline at end of file diff --git a/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/useDos.svg b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/useDos.svg new file mode 100644 index 000000000000..3a3248ed553e --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/useDos.svg @@ -0,0 +1,129 @@ +<svg viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink"> + + + <defs> + + <g id="thing"> + + + <g id="t0a"><use xlink:href="#t1a"/><use xlink:href="#t1b"/></g> + <g id="t0b"><use xlink:href="#t1a"/><use xlink:href="#t1b"/></g> + <g id="t1a"><use xlink:href="#t2a"/><use xlink:href="#t2b"/></g> + <g id="t1b"><use xlink:href="#t2a"/><use xlink:href="#t2b"/></g> + <g id="t2a"><use xlink:href="#t3a"/><use xlink:href="#t3b"/></g> + <g id="t2b"><use xlink:href="#t3a"/><use xlink:href="#t3b"/></g> + <g id="t3a"><use xlink:href="#t4a"/><use xlink:href="#t4b"/></g> + <g id="t3b"><use xlink:href="#t4a"/><use xlink:href="#t4b"/></g> + <g id="t4a"><use xlink:href="#t5a"/><use xlink:href="#t5b"/></g> + <g id="t4b"><use xlink:href="#t5a"/><use xlink:href="#t5b"/></g> + <g id="t5a"><use xlink:href="#t6a"/><use xlink:href="#t6b"/></g> + <g id="t5b"><use xlink:href="#t6a"/><use xlink:href="#t6b"/></g> + <g id="t6a"><use xlink:href="#t7a"/><use xlink:href="#t7b"/></g> + <g id="t6b"><use xlink:href="#t7a"/><use xlink:href="#t7b"/></g> + <g id="t7a"><use xlink:href="#t8a"/><use xlink:href="#t8b"/></g> + <g id="t7b"><use xlink:href="#t8a"/><use xlink:href="#t8b"/></g> + <g id="t8a"><use xlink:href="#t9a"/><use xlink:href="#t9b"/></g> + <g id="t8b"><use xlink:href="#t9a"/><use xlink:href="#t9b"/></g> + <g id="t9a"><use xlink:href="#t10a"/><use xlink:href="#t10b"/></g> + <g id="t9b"><use xlink:href="#t10a"/><use xlink:href="#t10b"/></g> + <g id="t10a"><use xlink:href="#t11a"/><use xlink:href="#t11b"/></g> + <g id="t10b"><use xlink:href="#t11a"/><use xlink:href="#t11b"/></g> + <g id="t11a"><use xlink:href="#t12a"/><use xlink:href="#t12b"/></g> + <g id="t11b"><use xlink:href="#t12a"/><use xlink:href="#t12b"/></g> + <g id="t12a"><use xlink:href="#t13a"/><use xlink:href="#t13b"/></g> + <g id="t12b"><use xlink:href="#t13a"/><use xlink:href="#t13b"/></g> + <g id="t13a"><use xlink:href="#t14a"/><use xlink:href="#t14b"/></g> + <g id="t13b"><use xlink:href="#t14a"/><use xlink:href="#t14b"/></g> + <g id="t14a"><use xlink:href="#t15a"/><use xlink:href="#t15b"/></g> + <g id="t14b"><use xlink:href="#t15a"/><use xlink:href="#t15b"/></g> + <g id="t15a"><use xlink:href="#t16a"/><use xlink:href="#t16b"/></g> + <g id="t15b"><use xlink:href="#t16a"/><use xlink:href="#t16b"/></g> + <g id="t16a"><use xlink:href="#t17a"/><use xlink:href="#t17b"/></g> + <g id="t16b"><use xlink:href="#t17a"/><use xlink:href="#t17b"/></g> + <g id="t17a"><use xlink:href="#t18a"/><use xlink:href="#t18b"/></g> + <g id="t17b"><use xlink:href="#t18a"/><use xlink:href="#t18b"/></g> + <g id="t18a"><use xlink:href="#t19a"/><use xlink:href="#t19b"/></g> + <g id="t18b"><use xlink:href="#t19a"/><use xlink:href="#t19b"/></g> + <g id="t19a"><use xlink:href="#t20a"/><use xlink:href="#t20b"/></g> + <g id="t19b"><use xlink:href="#t20a"/><use xlink:href="#t20b"/></g> + <g id="t20a"><use xlink:href="#t21a"/><use xlink:href="#t21b"/></g> + <g id="t20b"><use xlink:href="#t21a"/><use xlink:href="#t21b"/></g> + <g id="t21a"><use xlink:href="#t22a"/><use xlink:href="#t22b"/></g> + <g id="t21b"><use xlink:href="#t22a"/><use xlink:href="#t22b"/></g> + <g id="t22a"><use xlink:href="#t23a"/><use xlink:href="#t23b"/></g> + <g id="t22b"><use xlink:href="#t23a"/><use xlink:href="#t23b"/></g> + <g id="t23a"><use xlink:href="#t24a"/><use xlink:href="#t24b"/></g> + <g id="t23b"><use xlink:href="#t24a"/><use xlink:href="#t24b"/></g> + <g id="t24a"><use xlink:href="#t25a"/><use xlink:href="#t25b"/></g> + <g id="t24b"><use xlink:href="#t25a"/><use xlink:href="#t25b"/></g> + <g id="t25a"><use xlink:href="#t26a"/><use xlink:href="#t26b"/></g> + <g id="t25b"><use xlink:href="#t26a"/><use xlink:href="#t26b"/></g> + <g id="t26a"><use xlink:href="#t27a"/><use xlink:href="#t27b"/></g> + <g id="t26b"><use xlink:href="#t27a"/><use xlink:href="#t27b"/></g> + <g id="t27a"><use xlink:href="#t28a"/><use xlink:href="#t28b"/></g> + <g id="t27b"><use xlink:href="#t28a"/><use xlink:href="#t28b"/></g> + <g id="t28a"><use xlink:href="#t29a"/><use xlink:href="#t29b"/></g> + <g id="t28b"><use xlink:href="#t29a"/><use xlink:href="#t29b"/></g> + <g id="t29a"><use xlink:href="#t30a"/><use xlink:href="#t30b"/></g> + <g id="t29b"><use xlink:href="#t30a"/><use xlink:href="#t30b"/></g> + <g id="t30a"><use xlink:href="#t31a"/><use xlink:href="#t31b"/></g> + <g id="t30b"><use xlink:href="#t31a"/><use xlink:href="#t31b"/></g> + <g id="t31a"><use xlink:href="#t32a"/><use xlink:href="#t32b"/></g> + <g id="t31b"><use xlink:href="#t32a"/><use xlink:href="#t32b"/></g> + <g id="t32a"><use xlink:href="#t33a"/><use xlink:href="#t33b"/></g> + <g id="t32b"><use xlink:href="#t33a"/><use xlink:href="#t33b"/></g> + <g id="t33a"><use xlink:href="#t34a"/><use xlink:href="#t34b"/></g> + <g id="t33b"><use xlink:href="#t34a"/><use xlink:href="#t34b"/></g> + <g id="t34a"><use xlink:href="#t35a"/><use xlink:href="#t35b"/></g> + <g id="t34b"><use xlink:href="#t35a"/><use xlink:href="#t35b"/></g> + <g id="t35a"><use xlink:href="#t36a"/><use xlink:href="#t36b"/></g> + <g id="t35b"><use xlink:href="#t36a"/><use xlink:href="#t36b"/></g> + <g id="t36a"><use xlink:href="#t37a"/><use xlink:href="#t37b"/></g> + <g id="t36b"><use xlink:href="#t37a"/><use xlink:href="#t37b"/></g> + <g id="t37a"><use xlink:href="#t38a"/><use xlink:href="#t38b"/></g> + <g id="t37b"><use xlink:href="#t38a"/><use xlink:href="#t38b"/></g> + <g id="t38a"><use xlink:href="#t39a"/><use xlink:href="#t39b"/></g> + <g id="t38b"><use xlink:href="#t39a"/><use xlink:href="#t39b"/></g> + <g id="t39a"><use xlink:href="#t40a"/><use xlink:href="#t40b"/></g> + <g id="t39b"><use xlink:href="#t40a"/><use xlink:href="#t40b"/></g> + <g id="t40a"><use xlink:href="#t41a"/><use xlink:href="#t41b"/></g> + <g id="t40b"><use xlink:href="#t41a"/><use xlink:href="#t41b"/></g> + <g id="t41a"><use xlink:href="#t42a"/><use xlink:href="#t42b"/></g> + <g id="t41b"><use xlink:href="#t42a"/><use xlink:href="#t42b"/></g> + <g id="t42a"><use xlink:href="#t43a"/><use xlink:href="#t43b"/></g> + <g id="t42b"><use xlink:href="#t43a"/><use xlink:href="#t43b"/></g> + <g id="t43a"><use xlink:href="#t44a"/><use xlink:href="#t44b"/></g> + <g id="t43b"><use xlink:href="#t44a"/><use xlink:href="#t44b"/></g> + <g id="t44a"><use xlink:href="#t45a"/><use xlink:href="#t45b"/></g> + <g id="t44b"><use xlink:href="#t45a"/><use xlink:href="#t45b"/></g> + <g id="t45a"><use xlink:href="#t46a"/><use xlink:href="#t46b"/></g> + <g id="t45b"><use xlink:href="#t46a"/><use xlink:href="#t46b"/></g> + <g id="t46a"><use xlink:href="#t47a"/><use xlink:href="#t47b"/></g> + <g id="t46b"><use xlink:href="#t47a"/><use xlink:href="#t47b"/></g> + <g id="t47a"><use xlink:href="#t48a"/><use xlink:href="#t48b"/></g> + <g id="t47b"><use xlink:href="#t48a"/><use xlink:href="#t48b"/></g> + <g id="t48a"><use xlink:href="#t49a"/><use xlink:href="#t49b"/></g> + <g id="t48b"><use xlink:href="#t49a"/><use xlink:href="#t49b"/></g> + <g id="t49a"><use xlink:href="#t50a"/><use xlink:href="#t50b"/></g> + <g id="t49b"><use xlink:href="#t50a"/><use xlink:href="#t50b"/></g> + + + + <g id="t50a"> + <circle cx="0" cy="0" r="5" /> + </g> + + <g id="t50b"> + <circle cx="0" cy="0" r="5" /> + </g> + + + </g> + + </defs> + + <use x="5" y="5" xlink:href="#thing"/> + + +</svg> \ No newline at end of file diff --git a/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/xlinkLaughs.svg b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/xlinkLaughs.svg new file mode 100644 index 000000000000..c344a80ad932 --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/xlinkLaughs.svg @@ -0,0 +1,146 @@ +<?xml version="1.0" standalone="no"?> +<svg viewBox="0 0 512 512" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="512" height="512"> + <defs> + <g id="a0"> + <circle stroke="#000000" fill="#ffffff" fill-opacity="0.1" r="10"/> + </g> + </defs><defs> +<g id="a1"> +<use x="0" y="10" xlink:href="#a0" /> +<use x="10" y="10" xlink:href="#a0" /> +<use x="20" y="10" xlink:href="#a0" /> +<use x="30" y="10" xlink:href="#a0" /> +<use x="40" y="10" xlink:href="#a0" /> +<use x="50" y="10" xlink:href="#a0" /> +<use x="60" y="10" xlink:href="#a0" /> +<use x="70" y="10" xlink:href="#a0" /> +<use x="80" y="10" xlink:href="#a0" /> +<use x="90" y="10" xlink:href="#a0" /> +</g> +</defs> +<defs> +<g id="a2"> +<use x="0" y="10" xlink:href="#a1" /> +<use x="10" y="10" xlink:href="#a1" /> +<use x="20" y="10" xlink:href="#a1" /> +<use x="30" y="10" xlink:href="#a1" /> +<use x="40" y="10" xlink:href="#a1" /> +<use x="50" y="10" xlink:href="#a1" /> +<use x="60" y="10" xlink:href="#a1" /> +<use x="70" y="10" xlink:href="#a1" /> +<use x="80" y="10" xlink:href="#a1" /> +<use x="90" y="10" xlink:href="#a1" /> +</g> +</defs> +<defs> +<g id="a3"> +<use x="0" y="10" xlink:href="#a2" /> +<use x="10" y="10" xlink:href="#a2" /> +<use x="20" y="10" xlink:href="#a2" /> +<use x="30" y="10" xlink:href="#a2" /> +<use x="40" y="10" xlink:href="#a2" /> +<use x="50" y="10" xlink:href="#a2" /> +<use x="60" y="10" xlink:href="#a2" /> +<use x="70" y="10" xlink:href="#a2" /> +<use x="80" y="10" xlink:href="#a2" /> +<use x="90" y="10" xlink:href="#a2" /> +</g> +</defs> +<defs> +<g id="a4"> +<use x="0" y="10" xlink:href="#a3" /> +<use x="10" y="10" xlink:href="#a3" /> +<use x="20" y="10" xlink:href="#a3" /> +<use x="30" y="10" xlink:href="#a3" /> +<use x="40" y="10" xlink:href="#a3" /> +<use x="50" y="10" xlink:href="#a3" /> +<use x="60" y="10" xlink:href="#a3" /> +<use x="70" y="10" xlink:href="#a3" /> +<use x="80" y="10" xlink:href="#a3" /> +<use x="90" y="10" xlink:href="#a3" /> +</g> +</defs> +<defs> +<g id="a5"> +<use x="0" y="10" xlink:href="#a4" /> +<use x="10" y="10" xlink:href="#a4" /> +<use x="20" y="10" xlink:href="#a4" /> +<use x="30" y="10" xlink:href="#a4" /> +<use x="40" y="10" xlink:href="#a4" /> +<use x="50" y="10" xlink:href="#a4" /> +<use x="60" y="10" xlink:href="#a4" /> +<use x="70" y="10" xlink:href="#a4" /> +<use x="80" y="10" xlink:href="#a4" /> +<use x="90" y="10" xlink:href="#a4" /> +</g> +</defs> +<defs> +<g id="a6"> +<use x="0" y="10" xlink:href="#a5" /> +<use x="10" y="10" xlink:href="#a5" /> +<use x="20" y="10" xlink:href="#a5" /> +<use x="30" y="10" xlink:href="#a5" /> +<use x="40" y="10" xlink:href="#a5" /> +<use x="50" y="10" xlink:href="#a5" /> +<use x="60" y="10" xlink:href="#a5" /> +<use x="70" y="10" xlink:href="#a5" /> +<use x="80" y="10" xlink:href="#a5" /> +<use x="90" y="10" xlink:href="#a5" /> +</g> +</defs> +<defs> +<g id="a7"> +<use x="0" y="10" xlink:href="#a6" /> +<use x="10" y="10" xlink:href="#a6" /> +<use x="20" y="10" xlink:href="#a6" /> +<use x="30" y="10" xlink:href="#a6" /> +<use x="40" y="10" xlink:href="#a6" /> +<use x="50" y="10" xlink:href="#a6" /> +<use x="60" y="10" xlink:href="#a6" /> +<use x="70" y="10" xlink:href="#a6" /> +<use x="80" y="10" xlink:href="#a6" /> +<use x="90" y="10" xlink:href="#a6" /> +</g> +</defs> +<defs> +<g id="a8"> +<use x="0" y="10" xlink:href="#a7" /> +<use x="10" y="10" xlink:href="#a7" /> +<use x="20" y="10" xlink:href="#a7" /> +<use x="30" y="10" xlink:href="#a7" /> +<use x="40" y="10" xlink:href="#a7" /> +<use x="50" y="10" xlink:href="#a7" /> +<use x="60" y="10" xlink:href="#a7" /> +<use x="70" y="10" xlink:href="#a7" /> +<use x="80" y="10" xlink:href="#a7" /> +<use x="90" y="10" xlink:href="#a7" /> +</g> +</defs> +<defs> +<g id="a9"> +<use x="0" y="10" xlink:href="#a8" /> +<use x="10" y="10" xlink:href="#a8" /> +<use x="20" y="10" xlink:href="#a8" /> +<use x="30" y="10" xlink:href="#a8" /> +<use x="40" y="10" xlink:href="#a8" /> +<use x="50" y="10" xlink:href="#a8" /> +<use x="60" y="10" xlink:href="#a8" /> +<use x="70" y="10" xlink:href="#a8" /> +<use x="80" y="10" xlink:href="#a8" /> +<use x="90" y="10" xlink:href="#a8" /> +</g> +</defs> +<defs> +<g id="a10"> +<use x="0" y="10" xlink:href="#a9" /> +<use x="10" y="10" xlink:href="#a9" /> +<use x="20" y="10" xlink:href="#a9" /> +<use x="30" y="10" xlink:href="#a9" /> +<use x="40" y="10" xlink:href="#a9" /> +<use x="50" y="10" xlink:href="#a9" /> +<use x="60" y="10" xlink:href="#a9" /> +<use x="70" y="10" xlink:href="#a9" /> +<use x="80" y="10" xlink:href="#a9" /> +<use x="90" y="10" xlink:href="#a9" /> +</g> +</defs><use x="0" y="0" xlink:href="#a9" /></svg> \ No newline at end of file diff --git a/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/xlinkLoop.svg b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/xlinkLoop.svg new file mode 100644 index 000000000000..e8de02d74a56 --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/xlinkLoop.svg @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 500 500"> + <!-- ping:pong section to be removed --> + <g id="ping"> + <text style="font-weight: 700;" x="50" y="50">Ping</text> + <use href="#pong" /> + </g> + <g id="pong"> + <text x="50" y="100" style="font-weight: 700">Pong</text> + <use href="#ping" /> + </g> + <!-- nested loop --> + <g id="first"> + <text style="font-weight: 700;" x="50" y="50">1st</text> + <use href="#second" /> + </g> + <g id="second"> + <text style="font-weight: 700;" x="50" y="50">2nd</text> + <use href="#third" /> + </g> + <g id="third"> + <text style="font-weight: 700;" x="50" y="50">3rd</text> + <use href="#fourth" /> + </g> + <g id="fourth"> + <text style="font-weight: 700;" x="50" y="50">4th</text> + <use href="#first" /> + </g> + <!-- self reference to be removed --> + <use id="self" xlink:href="#self" /> +</svg> diff --git a/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/xlink_laughs.svg b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/xlink_laughs.svg new file mode 100644 index 000000000000..01c676a49dfe --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/xlink_laughs.svg @@ -0,0 +1,146 @@ +<?xml version="1.0" standalone="no"?> +<svg viewBox="0 0 512 512" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" x="0px" y="0px" width="512" height="512"> + <defs> + <g id="a0"> + <circle stroke="#000000" fill="#ffffff" fill-opacity="0.1" r="10"/> + </g> + </defs><defs> +<g id="a1"> +<use x="0" y="10" xlink:href="#a0" /> +<use x="10" y="10" xlink:href="#a0" /> +<use x="20" y="10" xlink:href="#a0" /> +<use x="30" y="10" xlink:href="#a0" /> +<use x="40" y="10" xlink:href="#a0" /> +<use x="50" y="10" xlink:href="#a0" /> +<use x="60" y="10" xlink:href="#a0" /> +<use x="70" y="10" xlink:href="#a0" /> +<use x="80" y="10" xlink:href="#a0" /> +<use x="90" y="10" xlink:href="#a0" /> +</g> +</defs> +<defs> +<g id="a2"> +<use x="0" y="10" xlink:href="#a1" /> +<use x="10" y="10" xlink:href="#a1" /> +<use x="20" y="10" xlink:href="#a1" /> +<use x="30" y="10" xlink:href="#a1" /> +<use x="40" y="10" xlink:href="#a1" /> +<use x="50" y="10" xlink:href="#a1" /> +<use x="60" y="10" xlink:href="#a1" /> +<use x="70" y="10" xlink:href="#a1" /> +<use x="80" y="10" xlink:href="#a1" /> +<use x="90" y="10" xlink:href="#a1" /> +</g> +</defs> +<defs> +<g id="a3"> +<use x="0" y="10" xlink:href="#a2" /> +<use x="10" y="10" xlink:href="#a2" /> +<use x="20" y="10" xlink:href="#a2" /> +<use x="30" y="10" xlink:href="#a2" /> +<use x="40" y="10" xlink:href="#a2" /> +<use x="50" y="10" xlink:href="#a2" /> +<use x="60" y="10" xlink:href="#a2" /> +<use x="70" y="10" xlink:href="#a2" /> +<use x="80" y="10" xlink:href="#a2" /> +<use x="90" y="10" xlink:href="#a2" /> +</g> +</defs> +<defs> +<g id="a4"> +<use x="0" y="10" xlink:href="#a3" /> +<use x="10" y="10" xlink:href="#a3" /> +<use x="20" y="10" xlink:href="#a3" /> +<use x="30" y="10" xlink:href="#a3" /> +<use x="40" y="10" xlink:href="#a3" /> +<use x="50" y="10" xlink:href="#a3" /> +<use x="60" y="10" xlink:href="#a3" /> +<use x="70" y="10" xlink:href="#a3" /> +<use x="80" y="10" xlink:href="#a3" /> +<use x="90" y="10" xlink:href="#a3" /> +</g> +</defs> +<defs> +<g id="a5"> +<use x="0" y="10" xlink:href="#a4" /> +<use x="10" y="10" xlink:href="#a4" /> +<use x="20" y="10" xlink:href="#a4" /> +<use x="30" y="10" xlink:href="#a4" /> +<use x="40" y="10" xlink:href="#a4" /> +<use x="50" y="10" xlink:href="#a4" /> +<use x="60" y="10" xlink:href="#a4" /> +<use x="70" y="10" xlink:href="#a4" /> +<use x="80" y="10" xlink:href="#a4" /> +<use x="90" y="10" xlink:href="#a4" /> +</g> +</defs> +<defs> +<g id="a6"> +<use x="0" y="10" xlink:href="#a5" /> +<use x="10" y="10" xlink:href="#a5" /> +<use x="20" y="10" xlink:href="#a5" /> +<use x="30" y="10" xlink:href="#a5" /> +<use x="40" y="10" xlink:href="#a5" /> +<use x="50" y="10" xlink:href="#a5" /> +<use x="60" y="10" xlink:href="#a5" /> +<use x="70" y="10" xlink:href="#a5" /> +<use x="80" y="10" xlink:href="#a5" /> +<use x="90" y="10" xlink:href="#a5" /> +</g> +</defs> +<defs> +<g id="a7"> +<use x="0" y="10" xlink:href="#a6" /> +<use x="10" y="10" xlink:href="#a6" /> +<use x="20" y="10" xlink:href="#a6" /> +<use x="30" y="10" xlink:href="#a6" /> +<use x="40" y="10" xlink:href="#a6" /> +<use x="50" y="10" xlink:href="#a6" /> +<use x="60" y="10" xlink:href="#a6" /> +<use x="70" y="10" xlink:href="#a6" /> +<use x="80" y="10" xlink:href="#a6" /> +<use x="90" y="10" xlink:href="#a6" /> +</g> +</defs> +<defs> +<g id="a8"> +<use x="0" y="10" xlink:href="#a7" /> +<use x="10" y="10" xlink:href="#a7" /> +<use x="20" y="10" xlink:href="#a7" /> +<use x="30" y="10" xlink:href="#a7" /> +<use x="40" y="10" xlink:href="#a7" /> +<use x="50" y="10" xlink:href="#a7" /> +<use x="60" y="10" xlink:href="#a7" /> +<use x="70" y="10" xlink:href="#a7" /> +<use x="80" y="10" xlink:href="#a7" /> +<use x="90" y="10" xlink:href="#a7" /> +</g> +</defs> +<defs> +<g id="a9"> +<use x="0" y="10" xlink:href="#a8" /> +<use x="10" y="10" xlink:href="#a8" /> +<use x="20" y="10" xlink:href="#a8" /> +<use x="30" y="10" xlink:href="#a8" /> +<use x="40" y="10" xlink:href="#a8" /> +<use x="50" y="10" xlink:href="#a8" /> +<use x="60" y="10" xlink:href="#a8" /> +<use x="70" y="10" xlink:href="#a8" /> +<use x="80" y="10" xlink:href="#a8" /> +<use x="90" y="10" xlink:href="#a8" /> +</g> +</defs> +<defs> +<g id="a10"> +<use x="0" y="10" xlink:href="#a9" /> +<use x="10" y="10" xlink:href="#a9" /> +<use x="20" y="10" xlink:href="#a9" /> +<use x="30" y="10" xlink:href="#a9" /> +<use x="40" y="10" xlink:href="#a9" /> +<use x="50" y="10" xlink:href="#a9" /> +<use x="60" y="10" xlink:href="#a9" /> +<use x="70" y="10" xlink:href="#a9" /> +<use x="80" y="10" xlink:href="#a9" /> +<use x="90" y="10" xlink:href="#a9" /> +</g> +</defs><use x="0" y="0" xlink:href="#a9" /></svg> \ No newline at end of file diff --git a/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/xmlOne.xml b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/xmlOne.xml new file mode 100644 index 000000000000..0566a4500531 --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/xmlOne.xml @@ -0,0 +1,12 @@ +<svg xmlns="http://www.w3.org/2000/svg"> + <test></test> + <image onload="alert(1)"></image> + <svg onload="alert(2)"></svg> + <script>alert(3)</script> + <defs onload="alert(4)"></defs> + <g onload="alert(5)"> + <circle onload="alert(6)" /> + <text onload="alert(7)"></text> + </g> + <ø:script src="//0x.lv/" /> +</svg> \ No newline at end of file diff --git a/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/xss.svg b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/xss.svg new file mode 100644 index 000000000000..f6aa93d242e9 --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Resource/Fixtures/DirtySVG/xss.svg @@ -0,0 +1,8 @@ +<?xml version="1.0" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg"> + <rect x="100" y="100" width="100" height="100" stroke="red" stroke-width="10" fill="white" /> + <script type="text/javascript"> + alert('XSS'); + </script> +</svg> \ No newline at end of file diff --git a/typo3/sysext/core/Tests/Functional/Resource/Security/SvgSanitizerTest.php b/typo3/sysext/core/Tests/Functional/Resource/Security/SvgSanitizerTest.php new file mode 100644 index 000000000000..109232378c51 --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/Resource/Security/SvgSanitizerTest.php @@ -0,0 +1,60 @@ +<?php + +declare(strict_types=1); + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +namespace TYPO3\CMS\Core\Tests\Functional\Resource\Security; + +use Symfony\Component\Finder\Finder; +use TYPO3\CMS\Core\Resource\Security\SvgSanitizer; +use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase; + +class SvgSanitizerTest extends FunctionalTestCase +{ + /** + * @return array<string, string[]> + */ + public function svgContentIsSanitizedDataProvider(): array + { + $basePath = dirname(__FILE__, 2) . '/Fixtures/'; + $finder = new Finder(); + $finder + ->files() + ->in($basePath . 'DirtySVG/') + ->name('*.svg'); + $data = []; + foreach ($finder as $file) { + $fileName = $file->getFilename(); + $data[$fileName] = ['DirtySVG/' . $fileName, 'CleanSVG/' . $fileName]; + } + return $data; + } + + /** + * @param string $filePath + * @param string $sanitizedFilePath + * @test + * @dataProvider svgContentIsSanitizedDataProvider + */ + public function svgContentIsSanitized($filePath, $sanitizedFilePath) + { + $basePath = dirname(__FILE__, 2) . '/Fixtures/'; + $sanitizer = new SvgSanitizer(); + self::assertStringEqualsFile( + $basePath . $sanitizedFilePath, + $sanitizer->sanitizeContent(file_get_contents($basePath . $filePath)) + ); + } +} diff --git a/typo3/sysext/core/composer.json b/typo3/sysext/core/composer.json index f6236a70d898..c9a286a46d47 100644 --- a/typo3/sysext/core/composer.json +++ b/typo3/sysext/core/composer.json @@ -34,6 +34,7 @@ "doctrine/instantiator": "^1.4", "doctrine/lexer": "^1.2.1", "egulias/email-validator": "^2.1", + "enshrined/svg-sanitize": "^0.14.0", "guzzlehttp/guzzle": "^7.2", "guzzlehttp/psr7": "^1.7.0", "nikic/php-parser": "^4.10.4", diff --git a/typo3/sysext/core/ext_localconf.php b/typo3/sysext/core/ext_localconf.php index e1378292d8a3..971b809d0aba 100644 --- a/typo3/sysext/core/ext_localconf.php +++ b/typo3/sysext/core/ext_localconf.php @@ -2,6 +2,7 @@ defined('TYPO3') or die(); +$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][\TYPO3\CMS\Core\Utility\GeneralUtility::class]['moveUploadedFile'][] = \TYPO3\CMS\Core\Resource\Security\SvgHookHandler::class . '->processMoveUploadedFile'; $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processDatamapClass'][] = \TYPO3\CMS\Core\Resource\Security\FileMetadataPermissionsAspect::class; $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processDatamapClass'][] = \TYPO3\CMS\Core\Hooks\BackendUserGroupIntegrityCheck::class; $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processDatamapClass'][] = \TYPO3\CMS\Core\Hooks\BackendUserPasswordCheck::class; diff --git a/typo3/sysext/install/Classes/Updates/SvgFilesSanitization.php b/typo3/sysext/install/Classes/Updates/SvgFilesSanitization.php new file mode 100644 index 000000000000..4c0b8823d5ba --- /dev/null +++ b/typo3/sysext/install/Classes/Updates/SvgFilesSanitization.php @@ -0,0 +1,200 @@ +<?php + +declare(strict_types=1); + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +namespace TYPO3\CMS\Install\Updates; + +use TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException; +use TYPO3\CMS\Core\Resource\File; +use TYPO3\CMS\Core\Resource\Filter\FileExtensionFilter; +use TYPO3\CMS\Core\Resource\ResourceStorage; +use TYPO3\CMS\Core\Resource\Security\SvgSanitizer; +use TYPO3\CMS\Core\Resource\StorageRepository; +use TYPO3\CMS\Core\Utility\GeneralUtility; + +class SvgFilesSanitization implements UpgradeWizardInterface, ConfirmableInterface +{ + /** + * @var StorageRepository + */ + protected $storageRepository; + + /** + * @var Confirmation + */ + protected $confirmation; + + public function __construct() + { + $this->storageRepository = GeneralUtility::makeInstance(StorageRepository::class); + $this->confirmation = new Confirmation( + 'Continue sanitizing SVG files?', + $this->getDescription(), + false, + 'sanitize, backup available', + 'cancel', + false + ); + } + + /** + * Return the identifier for this wizard + * This should be the same string as used in the ext_localconf class registration + * + * @return string + */ + public function getIdentifier(): string + { + // needs to be static for exact reference + return 'TYPO3\CMS\Install\Updates\SvgFilesSanitization'; + } + + /** + * Return the speaking name of this wizard + * + * @return string + */ + public function getTitle(): string + { + return 'Sanitize existing SVG files in fileadmin folder'; + } + + /** + * Return the description for this wizard + * + * @return string + */ + public function getDescription(): string + { + return 'This upgrade wizard will sanitize all SVG files located in local file storages. ' + . 'It is very likely that file contents will be changed.' . "\n" + . 'Before continuing, please ensure a proper backup of *.svg and *.svgz files is in place before continuing.'; + } + + /** + * Is an update necessary? + * + * Is used to determine whether a wizard needs to be run. + * Check if data for migration exists. + * + * @return bool + */ + public function updateNecessary(): bool + { + foreach ($this->resolveLocalStorages() as $storage) { + try { + $svgFiles = $this->resolveSvgFiles($storage); + } catch (InsufficientFolderAccessPermissionsException $exception) { + continue; + } + if (count($svgFiles) > 0) { + return true; + } + } + return false; + } + + /** + * Execute the update + * + * Called when a wizard reports that an update is necessary + * + * @return bool + */ + public function executeUpdate(): bool + { + return $this->processSvgFiles(); + } + + /** + * Returns an array of class names of Prerequisite classes + * + * This way a wizard can define dependencies like "database up-to-date" or + * "reference index updated" + * + * @return string[] + */ + public function getPrerequisites(): array + { + return []; + } + + /** + * Return a confirmation message instance + * + * @return Confirmation + */ + public function getConfirmation(): Confirmation + { + return $this->confirmation; + } + + /** + * @return ResourceStorage[] + */ + protected function resolveLocalStorages(): array + { + return array_filter( + $this->storageRepository->findByStorageType('Local'), + function (ResourceStorage $storage) { + return $storage->isWritable(); + } + ); + } + + /** + * @param ResourceStorage $storage + * @return File[] + * @throws InsufficientFolderAccessPermissionsException + */ + protected function resolveSvgFiles(ResourceStorage $storage): array + { + $filter = GeneralUtility::makeInstance(FileExtensionFilter::class); + $filter->setAllowedFileExtensions(['svg', 'svgz']); + return $storage + ->setFileAndFolderNameFilters([[$filter, 'filterFileList']]) + ->getFilesInFolder( + $storage->getRootLevelFolder(), + 0, + 0, + true, + true + ); + } + + protected function processSvgFiles(): bool + { + $successful = true; + $sanitizer = GeneralUtility::makeInstance(SvgSanitizer::class); + foreach ($this->resolveLocalStorages() as $storage) { + try { + $svgFiles = $this->resolveSvgFiles($storage); + } catch (InsufficientFolderAccessPermissionsException $exception) { + // @todo Add notice/warning for this upgrade process + $successful = false; + continue; + } + foreach ($svgFiles as $svgFile) { + $oldFileContent = $svgFile->getContents(); + $newFileContent = $sanitizer->sanitizeContent($oldFileContent); + if ($oldFileContent !== $newFileContent) { + $svgFile->setContents($newFileContent); + } + } + } + return $successful; + } +} diff --git a/typo3/sysext/install/ext_localconf.php b/typo3/sysext/install/ext_localconf.php index 42453d4937cc..59adc0850705 100644 --- a/typo3/sysext/install/ext_localconf.php +++ b/typo3/sysext/install/ext_localconf.php @@ -9,6 +9,8 @@ $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['taskcenterEx = \TYPO3\CMS\Install\Updates\TaskcenterExtractionUpdate::class; $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['sysActionExtension'] = \TYPO3\CMS\Install\Updates\SysActionExtractionUpdate::class; +$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['svgFilesSanitization'] + = \TYPO3\CMS\Install\Updates\SvgFilesSanitization::class; $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['shortcutRecordsMigration'] = \TYPO3\CMS\Install\Updates\ShortcutRecordsMigration::class; $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['databaseRowsUpdateWizard'] -- GitLab