‪TYPO3CMS  10.4
DefaultSanitizerBuilderTest.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
24 use TYPO3\HtmlSanitizer\Behavior;
25 use TYPO3\HtmlSanitizer\Sanitizer;
26 use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
27 
28 class ‪DefaultSanitizerBuilderTest extends FunctionalTestCase
29 {
33  protected ‪$initializeDatabase = false;
34 
35  public static function ‪isSanitizedDataProvider(): array
36  {
37  return [
38  '#010' => [
39  '<unknown unknown="unknown">value</unknown>',
40  '&lt;unknown unknown="unknown"&gt;value&lt;/unknown&gt;',
41  ],
42  '#011' => [
43  '<div class="nested"><unknown unknown="unknown">value</unknown></div>',
44  '<div class="nested">&lt;unknown unknown="unknown"&gt;value&lt;/unknown&gt;</div>',
45  ],
46  '#012' => [
47  '&lt;script&gt;alert(1)&lt;/script&gt;',
48  '&lt;script&gt;alert(1)&lt;/script&gt;',
49  ],
50  // @todo bug in https://github.com/Masterminds/html5-php/issues
51  // '#013' => [
52  // '<strong>Given that x < y and y > z...</strong>',
53  // '<strong>Given that x &lt; y and y &gt; z...</strong>',
54  // ],
55  '#020' => [
56  '<div unknown="unknown">value</div>',
57  '<div>value</div>',
58  ],
59  '#030' => [
60  '<div class="class">value</div>',
61  '<div class="class">value</div>',
62  ],
63  '#031' => [
64  '<div data-value="value">value</div>',
65  '<div data-value="value">value</div>',
66  ],
67  '#032' => [
68  '<div data-bool>value</div>',
69  '<div data-bool>value</div>',
70  ],
71  '#040' => [
72  '<img src="mailto:noreply@typo3.org" onerror="alert(1)">',
73  '',
74  ],
75  '#041' => [
76  '<img src="https://typo3.org/logo.svg" onerror="alert(1)">',
77  '<img src="https://typo3.org/logo.svg">',
78  ],
79  '#042' => [
80  '<img src="http://typo3.org/logo.svg" onerror="alert(1)">',
81  '<img src="http://typo3.org/logo.svg">',
82  ],
83  '#043' => [
84  '<img src="/typo3.org/logo.svg" onerror="alert(1)">',
85  '<img src="/typo3.org/logo.svg">',
86  ],
87  '#044' => [
88  '<img src="typo3.org/logo.svg" onerror="alert(1)">',
89  '<img src="typo3.org/logo.svg">',
90  ],
91  '#045' => [
92  '<img src="//typo3.org/logo.svg" onerror="alert(1)">',
93  '',
94  ],
95  '#050' => [
96  '<a href="https://typo3.org/" role="button">value</a>',
97  '<a href="https://typo3.org/" role="button">value</a>',
98  ],
99  '#051' => [
100  '<a href="ssh://example.org/" role="button">value</a>',
101  '<a role="button">value</a>',
102  ],
103  '#052' => [
104  '<a href="javascript:alert(1)" role="button">value</a>',
105  '<a role="button">value</a>',
106  ],
107  '#053' => [
108  '<a href="data:text/html;..." role="button">value</a>',
109  '<a role="button">value</a>',
110  ],
111  '#054' => [
112  '<a href="t3://page?uid=1" role="button">value</a>',
113  '<a href="t3://page?uid=1" role="button">value</a>',
114  ],
115  '#055' => [
116  '<a href="tel:123456789" role="button">value</a>',
117  '<a href="tel:123456789" role="button">value</a>',
118  ],
119  '#056' => [
120  // config.spamProtectEmailAddresses = [n]
121  '<a href="javascript:linkTo_UnCryptMailto(%27ocknvq%2CkphqBrtczku%5C%2Fmkghgt0fg%27);">email(at)domain.tld</a>',
122  '<a href="javascript:linkTo_UnCryptMailto(%27ocknvq%2CkphqBrtczku%5C%2Fmkghgt0fg%27);">email(at)domain.tld</a>',
123  ],
124  '#057' => [
125  // config.spamProtectEmailAddresses = ascii
126  '<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#115;&#111;&#109;&#101;&#46;&#98;&#111;&#100;&#121;&#64;&#116;&#101;&#115;&#116;&#46;&#116;&#121;&#112;&#111;&#51;&#46;&#111;&#114;&#103;">some.body(at)test.typo3(dot)org</a>',
127  // HTML entity encoding is not really a "protection", `Masterminds/html5-php` per default
128  // decodes those entities, which is good to have normalized attr values
129  '<a href="mailto:some.body@test.typo3.org">some.body(at)test.typo3(dot)org</a>',
130  ],
131  '#058' => [
132  // `... onclick="openPic(...)"` used in ContentObjectRenderer and AbstractMenuContentObject
133  '<a href="/" target="FEopenLink" onclick="openPic(\'\/\',\'FEopenLink\',\'width=200,height=300\');return false;">Link</a>',
134  '<a href="/" target="FEopenLink" onclick="openPic(\'\/\',\'FEopenLink\',\'width=200,height=300\');return false;">Link</a>'
135  ],
136  '#059' => [
137  // `... onclick="openPic(...)"` used in ContentObjectRenderer and AbstractMenuContentObject
138  '<a href="/index.php?eID=tx_cms_showpic" onclick="openPic(\'\/index.php?eID=tx_cms_showpic\u0026file=77\u0026md5=45a4b6287f68a61cf617a470e853d857461bc1d2\u0026parameters%5B0%5D=W10%3D\',\'thePicture\',\'width=1200,height=1799,status=0,menubar=0,=\'); return false;" target="thePicture"><img src="/logo.png"></a>',
139  '<a href="/index.php?eID=tx_cms_showpic" onclick="openPic(\'\/index.php?eID=tx_cms_showpic\u0026file=77\u0026md5=45a4b6287f68a61cf617a470e853d857461bc1d2\u0026parameters%5B0%5D=W10%3D\',\'thePicture\',\'width=1200,height=1799,status=0,menubar=0,=\'); return false;" target="thePicture"><img src="/logo.png"></a>'
140  ],
141  '#090' => [
142  '<p data-bool><span data-bool><strong data-bool>value</strong></span></p>',
143  '<p data-bool><span data-bool><strong data-bool>value</strong></span></p>'
144  ],
145  // @todo `style` used in Introduction Package, inline CSS should be removed
146  '#810' => [
147  '<span style="color: orange">value</span>',
148  '<span style="color: orange">value</span>',
149  ],
150  ];
151  }
152 
159  public function ‪isSanitized(string $payload, string $expectation): void
160  {
161  $factory = new ‪SanitizerBuilderFactory();
162  $builder = $factory->build('default');
163  $sanitizer = $builder->build();
164  self::assertSame($expectation, $sanitizer->sanitize($payload));
165  }
166 
170  public function ‪behaviorIsCachedInMemory(): void
171  {
172  $default = GeneralUtility::makeInstance(DefaultSanitizerBuilder::class);
173  $defaultSanitizer = $default->build();
174  $defaultBehavior = $this->‪resolveBehaviorFromSanitizer($defaultSanitizer);
175 
176  self::assertSame(
177  $defaultBehavior,
178  $this->‪resolveBehaviorFromSanitizer($default->build()),
179  'in-memory caching failed for same scope DefaultSanitizerBuilder'
180  );
181 
182  $extended = GeneralUtility::makeInstance(ExtendedSanitizerBuilder::class);
183  $extendedSanitizer = $extended->build();
184  $extendedBehavior = $this->‪resolveBehaviorFromSanitizer($extendedSanitizer);
185 
186  self::assertSame(
187  $extendedBehavior,
188  $this->‪resolveBehaviorFromSanitizer($extended->build()),
189  'in-memory caching failed for same scope ExtendedSanitizerBuilder'
190  );
191 
192  self::assertNotSame(
193  $defaultBehavior,
194  $extendedBehavior,
195  'in-memory cache violation for different scopes'
196  );
197  }
198 
199  private function ‪resolveBehaviorFromSanitizer(Sanitizer $sanitizer): Behavior
200  {
201  $visitorsProp = (new \ReflectionObject($sanitizer))->getProperty('visitors');
202  $visitorsProp->setAccessible(true);
203  $visitor = $visitorsProp->getValue($sanitizer)[0];
204 
205  $behaviorProp = (new \ReflectionObject($visitor))->getProperty('behavior');
206  $behaviorProp->setAccessible(true);
207  return $behaviorProp->getValue($visitor);
208  }
209 }
‪TYPO3\CMS\Core\Html\DefaultSanitizerBuilder
Definition: DefaultSanitizerBuilder.php:31
‪TYPO3\CMS\Core\Tests\Functional\Html\DefaultSanitizerBuilderTest\isSanitized
‪isSanitized(string $payload, string $expectation)
Definition: DefaultSanitizerBuilderTest.php:158
‪TYPO3\CMS\Core\Tests\Functional\Html\Fixtures\ExtendedSanitizerBuilder
Definition: ExtendedSanitizerBuilder.php:27
‪TYPO3\CMS\Core\Tests\Functional\Html\DefaultSanitizerBuilderTest\isSanitizedDataProvider
‪static isSanitizedDataProvider()
Definition: DefaultSanitizerBuilderTest.php:34
‪TYPO3\CMS\Core\Tests\Functional\Html
Definition: DefaultSanitizerBuilderTest.php:18
‪TYPO3\CMS\Core\Tests\Functional\Html\DefaultSanitizerBuilderTest\behaviorIsCachedInMemory
‪behaviorIsCachedInMemory()
Definition: DefaultSanitizerBuilderTest.php:169
‪TYPO3\CMS\Core\Tests\Functional\Html\DefaultSanitizerBuilderTest\resolveBehaviorFromSanitizer
‪resolveBehaviorFromSanitizer(Sanitizer $sanitizer)
Definition: DefaultSanitizerBuilderTest.php:198
‪TYPO3\CMS\Core\Tests\Functional\Html\DefaultSanitizerBuilderTest
Definition: DefaultSanitizerBuilderTest.php:29
‪TYPO3\CMS\Core\Tests\Functional\Html\DefaultSanitizerBuilderTest\$initializeDatabase
‪bool $initializeDatabase
Definition: DefaultSanitizerBuilderTest.php:32
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Core\Html\SanitizerBuilderFactory
Definition: SanitizerBuilderFactory.php:35