|
29 | 29 | package org.owasp.html;
|
30 | 30 |
|
31 | 31 | import java.util.Arrays;
|
| 32 | +import java.util.Collections; |
32 | 33 | import java.util.List;
|
33 | 34 | import java.util.Locale;
|
| 35 | +import java.util.Map; |
34 | 36 | import java.util.Set;
|
35 | 37 | import java.util.regex.Pattern;
|
36 | 38 | import java.util.stream.Collectors;
|
@@ -229,6 +231,96 @@ public static final void testStyleFiltering() {
|
229 | 231 | .allowStandardUrlProtocols()));
|
230 | 232 | }
|
231 | 233 |
|
| 234 | + @Test |
| 235 | + public void testSpecificStyleFilterung() { |
| 236 | + assertEquals( |
| 237 | + Arrays.stream(new String[] { |
| 238 | + "<h1>Header</h1>", |
| 239 | + "<p>Paragraph 1</p>", |
| 240 | + "<p>Click me out</p>", |
| 241 | + "<p></p>", |
| 242 | + "<p><b>Fancy</b> with <i><b>soupy</b></i><b> tags</b>.", |
| 243 | + "</p><p style=\"text-align:center\">Stylish Para 1</p>", |
| 244 | + "<p style=\"color:red\">Stylish Para 2</p>", |
| 245 | + ""}).collect(Collectors.joining("\n")), |
| 246 | + apply(new HtmlPolicyBuilder() |
| 247 | + .allowCommonInlineFormattingElements() |
| 248 | + .allowCommonBlockElements() |
| 249 | + .allowStyling(CssSchema.withProperties( |
| 250 | + List.of("color", "text-align", "font-size"))) |
| 251 | + .allowStandardUrlProtocols())); |
| 252 | + } |
| 253 | + |
| 254 | + @Test |
| 255 | + public void testUnionStyleFilterung() { |
| 256 | + assertEquals( |
| 257 | + Arrays.stream(new String[] { |
| 258 | + "<h1>Header</h1>", |
| 259 | + "<p>Paragraph 1</p>", |
| 260 | + "<p>Click me out</p>", |
| 261 | + "<p></p>", |
| 262 | + "<p><b>Fancy</b> with <i><b>soupy</b></i><b> tags</b>.", |
| 263 | + "</p><p style=\"text-align:center\">Stylish Para 1</p>", |
| 264 | + "<p style=\"color:red\">Stylish Para 2</p>", |
| 265 | + ""}).collect(Collectors.joining("\n")), |
| 266 | + apply(new HtmlPolicyBuilder() |
| 267 | + .allowCommonInlineFormattingElements() |
| 268 | + .allowCommonBlockElements() |
| 269 | + .allowStyling(CssSchema.withProperties( |
| 270 | + List.of("color", "text-align"))) |
| 271 | + .allowStyling( // union allowed style properties |
| 272 | + CssSchema.withProperties(List.of("font-size"))) |
| 273 | + .allowStandardUrlProtocols())); |
| 274 | + } |
| 275 | + |
| 276 | + @Test |
| 277 | + public void testCustomPropertyStyleFilterung() { |
| 278 | + assertEquals( |
| 279 | + Arrays.stream(new String[] { |
| 280 | + "<h1>Header</h1>", |
| 281 | + "<p>Paragraph 1</p>", |
| 282 | + "<p>Click me out</p>", |
| 283 | + "<p></p>", |
| 284 | + "<p><b>Fancy</b> with <i><b>soupy</b></i><b> tags</b>.", |
| 285 | + "</p><p style=\"text-align:center\">Stylish Para 1</p>", |
| 286 | + "<p>Stylish Para 2</p>", |
| 287 | + ""}).collect(Collectors.joining("\n")), |
| 288 | + apply(new HtmlPolicyBuilder() |
| 289 | + .allowCommonInlineFormattingElements() |
| 290 | + .allowCommonBlockElements() |
| 291 | + .allowStyling( |
| 292 | + CssSchema.withProperties( |
| 293 | + Map.of("text-align", |
| 294 | + new CssSchema.Property(0, |
| 295 | + Set.of("center"), |
| 296 | + Collections.emptyMap())))) |
| 297 | + .allowStandardUrlProtocols())); |
| 298 | + } |
| 299 | + |
| 300 | + @Test |
| 301 | + public void testCustomPropertyStyleFilterungDisallowed() { |
| 302 | + assertEquals( |
| 303 | + Arrays.stream(new String[] { |
| 304 | + "<h1>Header</h1>", |
| 305 | + "<p>Paragraph 1</p>", |
| 306 | + "<p>Click me out</p>", |
| 307 | + "<p></p>", |
| 308 | + "<p><b>Fancy</b> with <i><b>soupy</b></i><b> tags</b>.", |
| 309 | + "</p><p>Stylish Para 1</p>", |
| 310 | + "<p>Stylish Para 2</p>", |
| 311 | + ""}).collect(Collectors.joining("\n")), |
| 312 | + apply(new HtmlPolicyBuilder() |
| 313 | + .allowCommonInlineFormattingElements() |
| 314 | + .allowCommonBlockElements() |
| 315 | + .allowStyling( |
| 316 | + CssSchema.withProperties( |
| 317 | + Map.of("text-align", |
| 318 | + new CssSchema.Property(0, |
| 319 | + Set.of("left", "right"), |
| 320 | + Collections.emptyMap())))) |
| 321 | + .allowStandardUrlProtocols())); |
| 322 | + } |
| 323 | + |
232 | 324 | @Test
|
233 | 325 | public static final void testElementTransforming() {
|
234 | 326 | assertEquals(
|
@@ -289,6 +381,25 @@ public static final void testAllowUrlProtocols() {
|
289 | 381 | .allowUrlProtocols("http")));
|
290 | 382 | }
|
291 | 383 |
|
| 384 | + @Test |
| 385 | + public static final void testDisallowUrlProtocols() { |
| 386 | + assertEquals( |
| 387 | + Arrays.stream(new String[] { |
| 388 | + "Header", |
| 389 | + "Paragraph 1", |
| 390 | + "Click me out", |
| 391 | + "<img src=\"canary.png\" alt=\"local-canary\" />", |
| 392 | + "Fancy with soupy tags.", |
| 393 | + "Stylish Para 1", |
| 394 | + "Stylish Para 2", |
| 395 | + ""}).collect(Collectors.joining("\n")), |
| 396 | + apply(new HtmlPolicyBuilder() |
| 397 | + .allowElements("img") |
| 398 | + .allowAttributes("src", "alt").onElements("img") |
| 399 | + .allowUrlProtocols("http", "https") |
| 400 | + .disallowUrlProtocols("http"))); |
| 401 | + } |
| 402 | + |
292 | 403 | @Test
|
293 | 404 | public static final void testPossibleFalloutFromIssue5() {
|
294 | 405 | assertEquals(
|
@@ -434,6 +545,55 @@ public static final void testUrlChecksLayer() {
|
434 | 545 | );
|
435 | 546 | }
|
436 | 547 |
|
| 548 | + @Test |
| 549 | + public static final void testAllowProtocolRelativeUrls() { |
| 550 | + FilterUrlByProtocolAttributePolicy attributePolicy = |
| 551 | + new FilterUrlByProtocolAttributePolicy(List.of("http", "https")); |
| 552 | + attributePolicy.allowProtocolRelativeUrls(); |
| 553 | + |
| 554 | + assertEquals( |
| 555 | + "" |
| 556 | + + "Mailto link\n" |
| 557 | + + "<a href=\"http://example.com/\">Link</a>\n" |
| 558 | + + "<a href=\"https://example.com/\">Link</a>\n" |
| 559 | + + "<a href=\"//example.com/\">Link</a>\n", |
| 560 | + apply( |
| 561 | + new HtmlPolicyBuilder() |
| 562 | + .allowElements("a") |
| 563 | + .allowAttributes("href") |
| 564 | + .matching(attributePolicy) |
| 565 | + .onElements("a") |
| 566 | + .allowUrlProtocols("https", "http"), |
| 567 | + "" |
| 568 | + + "<a href=\"mailto:example@example.com/\">Mailto link</a>\n" |
| 569 | + + "<a href=\"http://example.com/\">Link</a>\n" |
| 570 | + + "<a href=\"https://example.com/\">Link</a>\n" |
| 571 | + + "<a href=\"//example.com/\">Link</a>\n" |
| 572 | + ) |
| 573 | + ); |
| 574 | + |
| 575 | + assertEquals( |
| 576 | + "" |
| 577 | + + "Mailto link\n" |
| 578 | + + "Link\n" |
| 579 | + + "<a href=\"https://example.com/\">Link</a>\n" |
| 580 | + + "Link\n", |
| 581 | + apply( |
| 582 | + new HtmlPolicyBuilder() |
| 583 | + .allowElements("a") |
| 584 | + .allowAttributes("href") |
| 585 | + .matching(attributePolicy) |
| 586 | + .onElements("a") |
| 587 | + .allowUrlProtocols("https"), |
| 588 | + "" |
| 589 | + + "<a href=\"mailto:example@example.com/\">Mailto link</a>\n" |
| 590 | + + "<a href=\"http://example.com/\">Link</a>\n" |
| 591 | + + "<a href=\"https://example.com/\">Link</a>\n" |
| 592 | + + "<a href=\"//example.com/\">Link</a>\n" |
| 593 | + ) |
| 594 | + ); |
| 595 | + } |
| 596 | + |
437 | 597 | @Test
|
438 | 598 | public static final void testDuplicateAttributesDoNotReachElementPolicy() {
|
439 | 599 | final int[] idCount = new int[1];
|
@@ -913,6 +1073,42 @@ public static final void testDirLi() {
|
913 | 1073 | "<dir compact=\"compact\"><li>something</li></dir>"));
|
914 | 1074 | }
|
915 | 1075 |
|
| 1076 | + @Test |
| 1077 | + public void testDisallowTextIn() { |
| 1078 | + HtmlPolicyBuilder sharedPolicyBuilder = new HtmlPolicyBuilder() |
| 1079 | + .allowElements("div") |
| 1080 | + .allowAttributes("style").onElements("div"); |
| 1081 | + |
| 1082 | + PolicyFactory allowPolicy = sharedPolicyBuilder.toFactory(); |
| 1083 | + assertEquals("<div style=\"display:node\">Some Text</div>", |
| 1084 | + allowPolicy.sanitize("<div style=\"display:node\">Some Text</div>")); |
| 1085 | + |
| 1086 | + PolicyFactory disallowTextPolicy = |
| 1087 | + sharedPolicyBuilder.disallowTextIn("div").toFactory(); |
| 1088 | + assertEquals("<div style=\"display:node\"></div>", |
| 1089 | + disallowTextPolicy.sanitize( |
| 1090 | + "<div style=\"display:node\">Some Text</div>")); |
| 1091 | + } |
| 1092 | + |
| 1093 | + @Test |
| 1094 | + public void testDisallowAttribute() { |
| 1095 | + HtmlPolicyBuilder sharedPolicyBuilder = new HtmlPolicyBuilder() |
| 1096 | + .allowElements("div", "p") |
| 1097 | + .allowAttributes("style").onElements("div", "p"); |
| 1098 | + |
| 1099 | + PolicyFactory allowPolicy = sharedPolicyBuilder.toFactory(); |
| 1100 | + assertEquals( |
| 1101 | + "<p style=\"display:node\">Some</p><div style=\"display:node\">Text</div>", |
| 1102 | + allowPolicy.sanitize( |
| 1103 | + "<p style=\"display:node\">Some</p><div style=\"display:node\">Text</div>")); |
| 1104 | + |
| 1105 | + PolicyFactory disallowTextPolicy = |
| 1106 | + sharedPolicyBuilder.disallowAttributes("style").onElements("p").toFactory(); |
| 1107 | + assertEquals("<p>Some</p><div style=\"display:node\">Text</div>", |
| 1108 | + disallowTextPolicy.sanitize( |
| 1109 | + "<p style=\"display:node\">Some</p><div style=\"display:node\">Text</div>")); |
| 1110 | + } |
| 1111 | + |
916 | 1112 | @Test
|
917 | 1113 | public static void testScriptTagWithCommentBlockContainingHtmlCommentEnd() {
|
918 | 1114 | PolicyFactory scriptSanitizer = new HtmlPolicyBuilder()
|
|
0 commit comments