SanitizersTest.java revision be666032a113a8af92bc557add8e83579cf0ef5c
1// Copyright (c) 2011, Mike Samuel
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions
6// are met:
7//
8// Redistributions of source code must retain the above copyright
9// notice, this list of conditions and the following disclaimer.
10// Redistributions in binary form must reproduce the above copyright
11// notice, this list of conditions and the following disclaimer in the
12// documentation and/or other materials provided with the distribution.
13// Neither the name of the OWASP nor the names of its contributors may
14// be used to endorse or promote products derived from this software
15// without specific prior written permission.
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27// POSSIBILITY OF SUCH DAMAGE.
28
29package org.owasp.html;
30
31import org.junit.Test;
32
33import junit.framework.TestCase;
34
35public class SanitizersTest extends TestCase {
36
37  @Test
38  public static final void testFormatting() {
39    assertEquals("", Sanitizers.FORMATTING.sanitize(null));
40    assertEquals("", Sanitizers.FORMATTING.sanitize(""));
41    assertEquals(
42        "Hello, World!",
43        Sanitizers.FORMATTING.sanitize("Hello, World!"));
44    assertEquals(
45        "Hello, <b>World</b>!",
46        Sanitizers.FORMATTING.sanitize("Hello, <b>World</b>!"));
47    assertEquals(
48        "Hello, <b>World</b>!",
49        Sanitizers.FORMATTING.sanitize(
50            "<p>Hello, <b onclick=alert(1337)>World</b>!</p>"));
51  }
52
53  @Test
54  public static final void testBlockElements() {
55    assertEquals("", Sanitizers.BLOCKS.sanitize(null));
56    assertEquals(
57        "Hello, World!",
58        Sanitizers.BLOCKS.sanitize("Hello, World!"));
59    assertEquals(
60        "Hello, World!",
61        Sanitizers.BLOCKS.sanitize("Hello, <b>World</b>!"));
62    assertEquals(
63        "<p>Hello, World!</p>",
64        Sanitizers.BLOCKS.sanitize(
65            "<p onclick=alert(1337)>Hello, <b>World</b>!</p>"));
66  }
67
68  @Test
69  public static final void testBlockAndFormattingElements() {
70    PolicyFactory s = Sanitizers.BLOCKS.and(Sanitizers.FORMATTING);
71    PolicyFactory r1 = Sanitizers.BLOCKS.and(Sanitizers.FORMATTING)
72        .and(Sanitizers.BLOCKS);
73    PolicyFactory r2 = Sanitizers.BLOCKS.and(Sanitizers.FORMATTING)
74        .and(Sanitizers.FORMATTING);
75    for (PolicyFactory f : new PolicyFactory[] { s, r1, r2 }) {
76      assertEquals("", f.sanitize(null));
77      assertEquals("Hello, World!", f.sanitize("Hello, World!"));
78      assertEquals("Hello, <b>World</b>!", f.sanitize("Hello, <b>World</b>!"));
79      assertEquals(
80          "<p>Hello, <b>World</b>!</p>",
81          f.sanitize("<p onclick=alert(1337)>Hello, <b>World</b>!</p>"));
82    }
83  }
84
85  @Test
86  public static final void testAndIntersects() {
87    PolicyFactory restrictedLink = new HtmlPolicyBuilder()
88       .allowElements("a")
89       .allowUrlProtocols("https")
90       .allowAttributes("href", "title").onElements("a")
91       .toFactory();
92    PolicyFactory inline = Sanitizers.FORMATTING.and(Sanitizers.LINKS);
93    String inputHtml =
94        "<a href='http://foo.com/'>Hello, <b>World</b></a>"
95        + "<a title='!' href='https://foo.com/#!'>!</a>";
96    PolicyFactory and1 = restrictedLink.and(inline);
97    PolicyFactory and2 = inline.and(restrictedLink);
98    assertEquals(
99        "https-only links",
100        "Hello, World<a title=\"!\" href=\"https://foo.com/#!\">!</a>",
101        restrictedLink.sanitize(inputHtml));
102    assertEquals(
103        "inline els",
104        "<a href=\"http://foo.com/\" rel=\"nofollow\">Hello, <b>World</b></a>"
105        + "<a href=\"https://foo.com/#!\" rel=\"nofollow\">!</a>",
106        inline.sanitize(inputHtml));
107    assertEquals(
108        "https-only links and inline els",
109        "Hello, <b>World</b>"
110        + "<a title=\"!\" href=\"https://foo.com/#!\" rel=\"nofollow\">!</a>",
111        and1.sanitize(inputHtml));
112    assertEquals(
113        "inline els and https-only links",
114        "Hello, <b>World</b>"
115        + "<a title=\"!\" href=\"https://foo.com/#!\" rel=\"nofollow\">!</a>",
116        and2.sanitize(inputHtml));
117  }
118
119  @Test
120  public static final void testImages() {
121    PolicyFactory s = Sanitizers.IMAGES;
122    assertEquals(
123        "foo", s.sanitize("<a href=\"javascript:alert(1337)\">foo</a>"));
124    assertEquals(
125        "<img src=\"foo.gif\" />", s.sanitize("<img src=\"foo.gif\">"));
126    assertEquals(
127        "", s.sanitize("<img src=\"javascript://alert(1337)\">"));
128    assertEquals(
129        "<img src=\"x.gif\" alt=\"y\""
130        + " width=\"96\" height=\"64\" border=\"0\" />",
131        s.sanitize(
132            "<img src=\"x.gif\" alt=\"y\" width=96 height=64 border=0>"));
133    assertEquals(
134        "<img src=\"x.png\" alt=\"y\" height=\"64\" border=\"0\" />",
135        s.sanitize(
136            "<img src=\"x.png\" alt=\"y\" width=\"widgy\" height=64 border=0>")
137        );
138  }
139
140  @Test
141  public static final void testLinks() {
142    PolicyFactory s = Sanitizers.LINKS;
143    assertEquals(
144        "<a href=\"foo.html\" rel=\"nofollow\">Link text</a>",
145        s.sanitize("<a href=\"foo.html\">Link text</a>"));
146    assertEquals(
147        "<a href=\"foo.html\" rel=\"nofollow\">Link text</a>",
148        s.sanitize(
149            "<a href=\"foo.html\" onclick=\"alert(1337)\">Link text</a>"));
150    assertEquals(
151        "<a href=\"http://example.com/x.html\" rel=\"nofollow\">Link text</a>",
152        s.sanitize(
153            "<a href=\"http://example.com/x.html\""
154            + " onclick=\"alert(1337)\">Link text</a>"));
155    assertEquals(
156        "<a href=\"https://example.com/x.html\" rel=\"nofollow\">Link text</a>",
157        s.sanitize(
158            "<a href=\"https://example.com/x.html\""
159            + " onclick=\"alert(1337)\">Link text</a>"));
160    assertEquals(
161        "<a href=\"//example.com/x.html\" rel=\"nofollow\">Link text</a>",
162        s.sanitize(
163            "<a href=\"//example.com/x.html\""
164            + " onclick=\"alert(1337)\">Link text</a>"));
165    assertEquals(
166        "Link text",
167        s.sanitize(
168            "<a href=\"javascript:alert(1337).html\""
169            + " onclick=\"alert(1337)\">Link text</a>"));
170    // Not a link.  Instead, an attempt to intercept URL references that has
171    // not been explicitly allowed.
172    assertEquals(
173        "Header text",
174        s.sanitize("<a name=\"header\" id=\"header\">Header text</a>"));
175  }
176
177  @Test
178  public static final void testIssue9StylesInTables() {
179    String input = ""
180        + "<table style=\"color: rgb(0, 0, 0);"
181        + " font-family: Arial, Geneva, sans-serif;\">"
182        + "<tbody>"
183        + "<tr>"
184        + "<th>Column One</th><th>Column Two</th>"
185        + "</tr>"
186        + "<tr>"
187        + "<td align=\"center\""
188        + " style=\"background-color: rgb(255, 255, 254);\">"
189        + "<font size=\"2\">Size 2</font></td>"
190        + "<td align=\"center\""
191        + " style=\"background-color: rgb(255, 255, 254);\">"
192        + "<font size=\"7\">Size 7</font></td>"
193        + "</tr>"
194        + "</tbody>"
195        + "</table>";
196    PolicyFactory s = new HtmlPolicyBuilder()
197        .allowElements("table", "tbody", "thead", "tr", "td", "th")
198        .allowCommonBlockElements()
199        .allowCommonInlineFormattingElements()
200        .allowStyling()
201        .allowAttributes("align").matching(true, "left", "center", "right")
202          .onElements("table", "tr", "td", "th")
203        .allowAttributes("size").onElements("font", "img")
204        .toFactory();
205    String sanitized = ""
206        + "<table style=\"font-family:&#34;Arial&#34;,&#34;Geneva&#34;,"
207        + "sans-serif;color:#000\">"
208        + "<tbody>"
209        + "<tr>"
210        + "<th>Column One</th><th>Column Two</th>"
211        + "</tr>"
212        + "<tr>"
213        + "<td align=\"center\" style=\"background-color:#fffffe\">"
214        + "<font size=\"2\">Size 2</font></td>"
215        + "<td align=\"center\" style=\"background-color:#fffffe\">"
216        + "<font size=\"7\">Size 7</font></td>"
217        + "</tr>"
218        + "</tbody>"
219        + "</table>";
220    assertEquals(sanitized, s.sanitize(input));
221  }
222}
223