34 $this->zendEscaper = new \Magento\Framework\ZendEscaper();
35 $this->loggerMock = $this->getMockForAbstractClass(\Psr\Log\LoggerInterface::class);
37 $objectManagerHelper->setBackwardCompatibleProperty($this->escaper,
'escaper', $this->zendEscaper);
38 $objectManagerHelper->setBackwardCompatibleProperty($this->escaper,
'logger', $this->loggerMock);
49 if ($codepoint < 0x80) {
50 return chr($codepoint);
52 if ($codepoint < 0x800) {
53 return chr($codepoint >> 6 & 0x3f | 0xc0)
54 . chr($codepoint & 0x3f | 0x80);
56 if ($codepoint < 0x10000) {
57 return chr($codepoint >> 12 & 0x0f | 0xe0)
58 . chr($codepoint >> 6 & 0x3f | 0x80)
59 . chr($codepoint & 0x3f | 0x80);
61 if ($codepoint < 0x110000) {
62 return chr($codepoint >> 18 & 0x07 | 0xf0)
63 . chr($codepoint >> 12 & 0x3f | 0x80)
64 . chr($codepoint >> 6 & 0x3f | 0x80)
65 . chr($codepoint & 0x3f | 0x80);
67 throw new \Exception(
'Codepoint requested outside of unicode range');
73 $immune = [
',',
'.',
'_'];
74 for ($chr = 0; $chr < 0xFF; $chr++) {
75 if ($chr >= 0x30 && $chr <= 0x39
76 || $chr >= 0x41 && $chr <= 0x5A
77 || $chr >= 0x61 && $chr <= 0x7A
80 $this->assertEquals($literal, $this->escaper->escapeJs($literal));
83 if (in_array($literal, $immune)) {
84 $this->assertEquals($literal, $this->escaper->escapeJs($literal));
86 $this->assertNotEquals(
88 $this->escaper->escapeJs($literal),
89 $literal .
' should be escaped!' 103 $this->assertEquals($expected, $this->escaper->escapeJs(
$data));
112 'zero length string' => [
'',
''],
113 'only digits' => [
'123',
'123'],
114 '<' => [
'<',
'\u003C'],
115 '>' => [
'>',
'\\u003E'],
116 '\'' => [
'\'',
'\\u0027'],
117 '"' => [
'"',
'\\u0022'],
118 '&' => [
'&',
'\\u0026'],
119 'Characters beyond ASCII value 255 to unicode escape' => [
'Ā',
'\\u0100'],
120 'Characters beyond Unicode BMP to unicode escape' => [
"\xF0\x90\x80\x80",
'\\uD800DC00'],
133 "\r" => [
"\r",
'\\u000D'],
134 "\n" => [
"\n",
'\\u000A'],
135 "\t" => [
"\t",
'\\u0009'],
136 "\0" => [
"\0",
'\\u0000'],
137 'Encode spaces for quoteless attribute protection' => [
' ',
'\\u0020'],
147 $actual = $this->escaper->escapeHtml(
$data, $allowedTags);
148 $this->assertEquals($expected, $actual);
157 $this->loggerMock->expects($this->once())
158 ->method(
'critical');
159 $actual = $this->escaper->escapeHtml(
$data, $allowedTags);
160 $this->assertEquals($expected, $actual);
169 'array -> [text with no tags, text with no allowed tags]' => [
170 'data' => [
'one',
'<two>three</two>'],
171 'expected' => [
'one',
'<two>three</two>'],
173 'text with special characters' => [
174 'data' =>
'&<>"\'&<>"'	',
175 'expected' =>
'&<>"'&<>"'	' 177 'text with multiple allowed tags, includes self closing tag' => [
178 'data' =>
'<span>some text in tags<br /></span>',
179 'expected' =>
'<span>some text in tags<br></span>',
180 'allowedTags' => [
'span',
'br'],
182 'text with multiple allowed tags and allowed attribute in double quotes' => [
183 'data' =>
'Only <span id="sku_max_allowed"><b>2</b></span> in stock',
184 'expected' =>
'Only <span id="sku_max_allowed"><b>2</b></span> in stock',
185 'allowedTags' => [
'span',
'b'],
187 'text with multiple allowed tags and allowed attribute in single quotes' => [
188 'data' =>
'Only <span id=\'sku_max_allowed\'><b>2</b></span> in stock',
189 'expected' =>
'Only <span id="sku_max_allowed"><b>2</b></span> in stock',
190 'allowedTags' => [
'span',
'b'],
192 'text with multiple allowed tags with allowed attribute' => [
193 'data' =>
'Only registered users can write reviews. Please <a href="%1">Sign in</a> or <a href="%2">' 194 .
'create an account</a>',
195 'expected' =>
'Only registered users can write reviews. Please <a href="%1">Sign in</a> or ' 196 .
'<a href="%2">create an account</a>',
197 'allowedTags' => [
'a'],
199 'text with not allowed attribute in single quotes' => [
200 'data' =>
'Only <span type=\'1\'><b>2</b></span> in stock',
201 'expected' =>
'Only <span><b>2</b></span> in stock',
202 'allowedTags' => [
'span',
'b'],
204 'text with allowed and not allowed tags' => [
205 'data' =>
'Only registered users can write reviews. Please <a href="%1">Sign in<span>three</span></a> ' 206 .
'or <a href="%2"><span id="action">create an account</span></a>',
207 'expected' =>
'Only registered users can write reviews. Please <a href="%1">Sign inthree</a> or ' 208 .
'<a href="%2">create an account</a>',
209 'allowedTags' => [
'a'],
211 'text with allowed and not allowed tags, with allowed and not allowed attributes' => [
212 'data' =>
'Some test <span>text in span tag</span> <strong>text in strong tag</strong> ' 213 .
'<a type="some-type" href="http://domain.com/" onclick="alert(1)">Click here</a><script>alert(1)' 215 'expected' =>
'Some test <span>text in span tag</span> text in strong tag <a href="http://domain.com/">' 216 .
'Click here</a>alert(1)',
217 'allowedTags' => [
'a',
'span'],
219 'text with html comment' => [
220 'data' =>
'Only <span><b>2</b></span> in stock <!-- HTML COMMENT -->',
221 'expected' =>
'Only <span><b>2</b></span> in stock <!-- HTML COMMENT -->',
222 'allowedTags' => [
'span',
'b'],
224 'text with non ascii characters' => [
225 'data' => [
'абвгд',
'مثال',
'幸福'],
226 'expected' => [
'абвгд',
'مثال',
'幸福'],
229 'html and body tags' => [
230 'data' =>
'<html><body><span>String</span></body></html>',
231 'expected' =>
'<span>String</span>',
232 'allowedTags' => [
'span'],
235 'data' =>
'<some tag> some text',
236 'expected' =>
' some text',
237 'allowedTags' => [
'span'],
248 'text with allowed script tag' => [
249 'data' =>
'<span><script>some text in tags</script></span>',
250 'expected' =>
'<span>some text in tags</span>',
251 'allowedTags' => [
'span',
'script'],
253 'text with invalid html' => [
254 'data' =>
'<spa>n id="id1">Some string</span>',
255 'expected' =>
'n id="id1">Some string',
256 'allowedTags' => [
'span'],
266 $data =
'http://example.com/search?term=this+%26+that&view=list';
267 $expected =
'http://example.com/search?term=this+%26+that&view=list';
268 $this->assertEquals($expected, $this->escaper->escapeUrl(
$data));
269 $this->assertEquals($expected, $this->escaper->escapeUrl($expected));
277 $data = [
"Don't do that.",
'lost_key' =>
"Can't do that."];
278 $expected = [
"Don\\'t do that.",
"Can\\'t do that."];
279 $this->assertEquals($expected, $this->escaper->escapeJsQuote(
$data));
280 $this->assertEquals($expected[0], $this->escaper->escapeJsQuote(
$data[0]));
288 $data =
"Text with 'single' and \"double\" quotes";
290 "Text with 'single' and "double" quotes",
291 "Text with \\'single\\' and \\"double\\" quotes",
293 $this->assertEquals($expected[0], $this->escaper->escapeQuote(
$data));
294 $this->assertEquals($expected[1], $this->escaper->escapeQuote(
$data,
true));
305 $this->assertEquals($expected, $this->escaper->escapeXssInUrl($input));
316 'javascript%3Aalert%28String.fromCharCode%280x78%29%2BString.' 317 .
'fromCharCode%280x73%29%2BString.fromCharCode%280x73%29%29',
318 ':alert%28String.fromCharCode%280x78%29%2BString.' 319 .
'fromCharCode%280x73%29%2BString.fromCharCode%280x73%29%29' 322 'http://test.com/?redirect=JAVASCRIPT:alert%281%29',
323 'http://test.com/?redirect=:alert%281%29',
326 'http://test.com/?redirect=javascript:alert%281%29',
327 'http://test.com/?redirect=:alert%281%29',
330 'http://test.com/?redirect=JavaScript:alert%281%29',
331 'http://test.com/?redirect=:alert%281%29',
334 'http://test.com/?redirect=javascript:alert(1)',
335 'http://test.com/?redirect=:alert(1)',
338 'http://test.com/?redirect=javascript:alert(1)&test=1',
339 'http://test.com/?redirect=:alert(1)&test=1',
342 'http://test.com/?redirect=\x6A\x61\x76\x61\x73\x63\x72\x69\x70\x74:alert(1)',
343 'http://test.com/?redirect=:alert(1)',
346 'http://test.com/?redirect=vbscript:alert(1)',
347 'http://test.com/?redirect=:alert(1)',
350 'http://test.com/?redirect=data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg',
351 'http://test.com/?redirect=:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg',
354 'http://test.com/?redirect=data%3Atext%2Fhtml%3Bbase64%2CPHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg',
355 'http://test.com/?redirect=:text%2Fhtml%3Bbase64%2CPHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg',
358 'http://test.com/?redirect=\x64\x61\x74\x61\x3a\x74\x65\x78\x74x2cCPHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg',
359 'http://test.com/?redirect=:\x74\x65\x78\x74x2cCPHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg',
testEscapeJs($data, $expected)
testEscapeHtml($data, $expected, $allowedTags=[])
testEscapeHtmlWithInvalidData($data, $expected, $allowedTags=[])
testEscapeJsEscapesOwaspRecommendedRanges()
escapeHtmlInvalidDataProvider()
codepointToUtf8($codepoint)
testEscapeXssInUrl($input, $expected)