Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(193)

Side by Side Diff: third_party/WebKit/Source/core/svg/UnsafeSVGAttributeSanitizationTest.cpp

Issue 1681553002: Add support for 'href' (w/o XLink NS) for various SVG elements (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase; update comment Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // FIXME(dominicc): Poor confused check-webkit-style demands Attribute.h here. 5 // FIXME(dominicc): Poor confused check-webkit-style demands Attribute.h here.
6 #include "core/dom/Attribute.h" 6 #include "core/dom/Attribute.h"
7 7
8 #include "core/HTMLNames.h" 8 #include "core/HTMLNames.h"
9 #include "core/SVGNames.h" 9 #include "core/SVGNames.h"
10 #include "core/XLinkNames.h" 10 #include "core/XLinkNames.h"
(...skipping 16 matching lines...) Expand all
27 #include "wtf/Vector.h" 27 #include "wtf/Vector.h"
28 #include "wtf/text/AtomicString.h" 28 #include "wtf/text/AtomicString.h"
29 #include "wtf/text/WTFString.h" 29 #include "wtf/text/WTFString.h"
30 30
31 // Test that SVG content with JavaScript URLs is sanitized by removing 31 // Test that SVG content with JavaScript URLs is sanitized by removing
32 // the URLs. This sanitization happens when the content is pasted or 32 // the URLs. This sanitization happens when the content is pasted or
33 // drag-dropped into an editable element. 33 // drag-dropped into an editable element.
34 // 34 //
35 // There are two vectors for JavaScript URLs in SVG content: 35 // There are two vectors for JavaScript URLs in SVG content:
36 // 36 //
37 // 1. Attributes, for example xlink:href in an <svg:a> element. 37 // 1. Attributes, for example xlink:href/href in an <svg:a> element.
38 // 2. Animations which set those attributes, for example 38 // 2. Animations which set those attributes, for example
39 // <animate attributeName="xlink:href" values="javascript:... 39 // <animate attributeName="xlink:href" values="javascript:...
40 // 40 //
41 // The following SVG elements, although related to animation, cannot 41 // The following SVG elements, although related to animation, cannot
42 // set JavaScript URLs: 42 // set JavaScript URLs:
43 // 43 //
44 // - 'discard' can only remove elements, not set their attributes 44 // - 'discard' can only remove elements, not set their attributes
45 // - 'animateMotion' does not use attribute name and produces floats 45 // - 'animateMotion' does not use attribute name and produces floats
46 // - 'animateTransform' can only animate transform lists 46 // - 'animateTransform' can only animate transform lists
47 47
(...skipping 24 matching lines...) Expand all
72 72
73 // Integration tests. 73 // Integration tests.
74 74
75 TEST( 75 TEST(
76 UnsafeSVGAttributeSanitizationTest, 76 UnsafeSVGAttributeSanitizationTest,
77 pasteAnchor_javaScriptHrefIsStripped) 77 pasteAnchor_javaScriptHrefIsStripped)
78 { 78 {
79 OwnPtr<DummyPageHolder> pageHolder = DummyPageHolder::create(IntSize(1, 1)); 79 OwnPtr<DummyPageHolder> pageHolder = DummyPageHolder::create(IntSize(1, 1));
80 static const char unsafeContent[] = 80 static const char unsafeContent[] =
81 "<svg xmlns='http://www.w3.org/2000/svg' " 81 "<svg xmlns='http://www.w3.org/2000/svg' "
82 " width='1cm' height='1cm'>"
83 " <a href='javascript:alert()'></a>"
84 "</svg>";
85 String sanitizedContent =
86 contentAfterPastingHTML(pageHolder.get(), unsafeContent);
87
88 EXPECT_TRUE(sanitizedContent.contains("</a>")) <<
89 "We should have pasted *something*; the document is: " <<
90 sanitizedContent.utf8().data();
91 EXPECT_FALSE(sanitizedContent.contains(":alert()")) <<
92 "The JavaScript URL is unsafe and should have been stripped; "
93 "instead: " <<
94 sanitizedContent.utf8().data();
95 }
96
97 TEST(
98 UnsafeSVGAttributeSanitizationTest,
99 pasteAnchor_javaScriptXlinkHrefIsStripped)
100 {
101 OwnPtr<DummyPageHolder> pageHolder = DummyPageHolder::create(IntSize(1, 1));
102 static const char unsafeContent[] =
103 "<svg xmlns='http://www.w3.org/2000/svg' "
82 " xmlns:xlink='http://www.w3.org/1999/xlink'" 104 " xmlns:xlink='http://www.w3.org/1999/xlink'"
83 " width='1cm' height='1cm'>" 105 " width='1cm' height='1cm'>"
84 " <a xlink:href='javascript:alert()'></a>" 106 " <a xlink:href='javascript:alert()'></a>"
85 "</svg>"; 107 "</svg>";
86 String sanitizedContent = 108 String sanitizedContent =
87 contentAfterPastingHTML(pageHolder.get(), unsafeContent); 109 contentAfterPastingHTML(pageHolder.get(), unsafeContent);
88 110
89 EXPECT_TRUE(sanitizedContent.contains("</a>")) << 111 EXPECT_TRUE(sanitizedContent.contains("</a>")) <<
90 "We should have pasted *something*; the document is: " << 112 "We should have pasted *something*; the document is: " <<
91 sanitizedContent.utf8().data(); 113 sanitizedContent.utf8().data();
92 EXPECT_FALSE(sanitizedContent.contains(":alert()")) << 114 EXPECT_FALSE(sanitizedContent.contains(":alert()")) <<
93 "The JavaScript URL is unsafe and should have been stripped; " 115 "The JavaScript URL is unsafe and should have been stripped; "
94 "instead: " << 116 "instead: " <<
95 sanitizedContent.utf8().data(); 117 sanitizedContent.utf8().data();
96 } 118 }
97 119
98 TEST( 120 TEST(
99 UnsafeSVGAttributeSanitizationTest, 121 UnsafeSVGAttributeSanitizationTest,
100 pasteAnchor_javaScriptHrefIsStripped_caseAndEntityInProtocol) 122 pasteAnchor_javaScriptHrefIsStripped_caseAndEntityInProtocol)
101 { 123 {
102 OwnPtr<DummyPageHolder> pageHolder = DummyPageHolder::create(IntSize(1, 1)); 124 OwnPtr<DummyPageHolder> pageHolder = DummyPageHolder::create(IntSize(1, 1));
103 static const char unsafeContent[] = 125 static const char unsafeContent[] =
104 "<svg xmlns='http://www.w3.org/2000/svg' " 126 "<svg xmlns='http://www.w3.org/2000/svg' "
127 " width='1cm' height='1cm'>"
128 " <a href='j&#x41;vascriPT:alert()'></a>"
129 "</svg>";
130 String sanitizedContent =
131 contentAfterPastingHTML(pageHolder.get(), unsafeContent);
132
133 EXPECT_TRUE(sanitizedContent.contains("</a>")) <<
134 "We should have pasted *something*; the document is: " <<
135 sanitizedContent.utf8().data();
136 EXPECT_FALSE(sanitizedContent.contains(":alert()")) <<
137 "The JavaScript URL is unsafe and should have been stripped; "
138 "instead: " <<
139 sanitizedContent.utf8().data();
140 }
141
142 TEST(
143 UnsafeSVGAttributeSanitizationTest,
144 pasteAnchor_javaScriptXlinkHrefIsStripped_caseAndEntityInProtocol)
145 {
146 OwnPtr<DummyPageHolder> pageHolder = DummyPageHolder::create(IntSize(1, 1));
147 static const char unsafeContent[] =
148 "<svg xmlns='http://www.w3.org/2000/svg' "
105 " xmlns:xlink='http://www.w3.org/1999/xlink'" 149 " xmlns:xlink='http://www.w3.org/1999/xlink'"
106 " width='1cm' height='1cm'>" 150 " width='1cm' height='1cm'>"
107 " <a xlink:href='j&#x41;vascriPT:alert()'></a>" 151 " <a xlink:href='j&#x41;vascriPT:alert()'></a>"
108 "</svg>"; 152 "</svg>";
109 String sanitizedContent = 153 String sanitizedContent =
110 contentAfterPastingHTML(pageHolder.get(), unsafeContent); 154 contentAfterPastingHTML(pageHolder.get(), unsafeContent);
111 155
112 EXPECT_TRUE(sanitizedContent.contains("</a>")) << 156 EXPECT_TRUE(sanitizedContent.contains("</a>")) <<
113 "We should have pasted *something*; the document is: " << 157 "We should have pasted *something*; the document is: " <<
114 sanitizedContent.utf8().data(); 158 sanitizedContent.utf8().data();
115 EXPECT_FALSE(sanitizedContent.contains(":alert()")) << 159 EXPECT_FALSE(sanitizedContent.contains(":alert()")) <<
116 "The JavaScript URL is unsafe and should have been stripped; " 160 "The JavaScript URL is unsafe and should have been stripped; "
117 "instead: " << 161 "instead: " <<
118 sanitizedContent.utf8().data(); 162 sanitizedContent.utf8().data();
119 } 163 }
120 164
121 TEST( 165 TEST(
122 UnsafeSVGAttributeSanitizationTest, 166 UnsafeSVGAttributeSanitizationTest,
123 pasteAnchor_javaScriptHrefIsStripped_entityWithoutSemicolonInProtocol) 167 pasteAnchor_javaScriptHrefIsStripped_entityWithoutSemicolonInProtocol)
124 { 168 {
125 OwnPtr<DummyPageHolder> pageHolder = DummyPageHolder::create(IntSize(1, 1)); 169 OwnPtr<DummyPageHolder> pageHolder = DummyPageHolder::create(IntSize(1, 1));
126 static const char unsafeContent[] = 170 static const char unsafeContent[] =
127 "<svg xmlns='http://www.w3.org/2000/svg' " 171 "<svg xmlns='http://www.w3.org/2000/svg' "
172 " width='1cm' height='1cm'>"
173 " <a href='jav&#x61script:alert()'></a>"
174 "</svg>";
175 String sanitizedContent =
176 contentAfterPastingHTML(pageHolder.get(), unsafeContent);
177
178 EXPECT_TRUE(sanitizedContent.contains("</a>")) <<
179 "We should have pasted *something*; the document is: " <<
180 sanitizedContent.utf8().data();
181 EXPECT_FALSE(sanitizedContent.contains(":alert()")) <<
182 "The JavaScript URL is unsafe and should have been stripped; "
183 "instead: " <<
184 sanitizedContent.utf8().data();
185 }
186
187 TEST(
188 UnsafeSVGAttributeSanitizationTest,
189 pasteAnchor_javaScriptXlinkHrefIsStripped_entityWithoutSemicolonInProtocol)
190 {
191 OwnPtr<DummyPageHolder> pageHolder = DummyPageHolder::create(IntSize(1, 1));
192 static const char unsafeContent[] =
193 "<svg xmlns='http://www.w3.org/2000/svg' "
128 " xmlns:xlink='http://www.w3.org/1999/xlink'" 194 " xmlns:xlink='http://www.w3.org/1999/xlink'"
129 " width='1cm' height='1cm'>" 195 " width='1cm' height='1cm'>"
130 " <a xlink:href='jav&#x61script:alert()'></a>" 196 " <a xlink:href='jav&#x61script:alert()'></a>"
131 "</svg>"; 197 "</svg>";
132 String sanitizedContent = 198 String sanitizedContent =
133 contentAfterPastingHTML(pageHolder.get(), unsafeContent); 199 contentAfterPastingHTML(pageHolder.get(), unsafeContent);
134 200
135 EXPECT_TRUE(sanitizedContent.contains("</a>")) << 201 EXPECT_TRUE(sanitizedContent.contains("</a>")) <<
136 "We should have pasted *something*; the document is: " << 202 "We should have pasted *something*; the document is: " <<
137 sanitizedContent.utf8().data(); 203 sanitizedContent.utf8().data();
138 EXPECT_FALSE(sanitizedContent.contains(":alert()")) << 204 EXPECT_FALSE(sanitizedContent.contains(":alert()")) <<
139 "The JavaScript URL is unsafe and should have been stripped; " 205 "The JavaScript URL is unsafe and should have been stripped; "
140 "instead: " << 206 "instead: " <<
141 sanitizedContent.utf8().data(); 207 sanitizedContent.utf8().data();
142 } 208 }
143 209
144 // Other sanitization integration tests are layout tests that use 210 // Other sanitization integration tests are layout tests that use
145 // document.execCommand('Copy') to source content that they later 211 // document.execCommand('Copy') to source content that they later
146 // paste. However SVG animation elements are not serialized when 212 // paste. However SVG animation elements are not serialized when
147 // copying, which means we can't test sanitizing these attributes in 213 // copying, which means we can't test sanitizing these attributes in
148 // layout tests: there is nowhere to source the unsafe content from. 214 // layout tests: there is nowhere to source the unsafe content from.
149 TEST( 215 TEST(
150 UnsafeSVGAttributeSanitizationTest, 216 UnsafeSVGAttributeSanitizationTest,
151 pasteAnimatedAnchor_javaScriptHrefIsStripped_caseAndEntityInProtocol) 217 pasteAnimatedAnchor_javaScriptHrefIsStripped_caseAndEntityInProtocol)
152 { 218 {
153 OwnPtr<DummyPageHolder> pageHolder = DummyPageHolder::create(IntSize(1, 1)); 219 OwnPtr<DummyPageHolder> pageHolder = DummyPageHolder::create(IntSize(1, 1));
154 static const char unsafeContent[] = 220 static const char unsafeContent[] =
155 "<svg xmlns='http://www.w3.org/2000/svg' " 221 "<svg xmlns='http://www.w3.org/2000/svg' "
222 " width='1cm' height='1cm'>"
223 " <a href='https://www.google.com/'>"
224 " <animate attributeName='href' values='evil;J&#x61VaSCRIpT:alert()'> "
225 " </a>"
226 "</svg>";
227 String sanitizedContent =
228 contentAfterPastingHTML(pageHolder.get(), unsafeContent);
229
230 EXPECT_TRUE(sanitizedContent.contains("<a href=\"https://www.goo")) <<
231 "We should have pasted *something*; the document is: " <<
232 sanitizedContent.utf8().data();
233 EXPECT_FALSE(sanitizedContent.contains(":alert()")) <<
234 "The JavaScript URL is unsafe and should have been stripped; "
235 "instead: " <<
236 sanitizedContent.utf8().data();
237 }
238
239 TEST(
240 UnsafeSVGAttributeSanitizationTest,
241 pasteAnimatedAnchor_javaScriptXlinkHrefIsStripped_caseAndEntityInProtocol)
242 {
243 OwnPtr<DummyPageHolder> pageHolder = DummyPageHolder::create(IntSize(1, 1));
244 static const char unsafeContent[] =
245 "<svg xmlns='http://www.w3.org/2000/svg' "
156 " xmlns:xlink='http://www.w3.org/1999/xlink'" 246 " xmlns:xlink='http://www.w3.org/1999/xlink'"
157 " width='1cm' height='1cm'>" 247 " width='1cm' height='1cm'>"
158 " <a xlink:href='https://www.google.com/'>" 248 " <a xlink:href='https://www.google.com/'>"
159 " <animate xmlns:ng='http://www.w3.org/1999/xlink' " 249 " <animate xmlns:ng='http://www.w3.org/1999/xlink' "
160 " attributeName='ng:href' values='evil;J&#x61VaSCRIpT:alert( )'>" 250 " attributeName='ng:href' values='evil;J&#x61VaSCRIpT:alert( )'>"
161 " </a>" 251 " </a>"
162 "</svg>"; 252 "</svg>";
163 String sanitizedContent = 253 String sanitizedContent =
164 contentAfterPastingHTML(pageHolder.get(), unsafeContent); 254 contentAfterPastingHTML(pageHolder.get(), unsafeContent);
165 255
(...skipping 18 matching lines...) Expand all
184 RefPtrWillBeRawPtr<Document> document = Document::create(); 274 RefPtrWillBeRawPtr<Document> document = Document::create();
185 RefPtrWillBeRawPtr<SVGElement> target = SVGAElement::create(*document); 275 RefPtrWillBeRawPtr<SVGElement> target = SVGAElement::create(*document);
186 RefPtrWillBeRawPtr<SVGAnimateElement> element = SVGAnimateElement::create(*d ocument); 276 RefPtrWillBeRawPtr<SVGAnimateElement> element = SVGAnimateElement::create(*d ocument);
187 element->setTargetElement(target.get()); 277 element->setTargetElement(target.get());
188 element->setAttributeName(XLinkNames::hrefAttr); 278 element->setAttributeName(XLinkNames::hrefAttr);
189 279
190 // Sanity check that xlink:href was identified as a "string" attribute 280 // Sanity check that xlink:href was identified as a "string" attribute
191 EXPECT_EQ(AnimatedString, element->animatedPropertyType()); 281 EXPECT_EQ(AnimatedString, element->animatedPropertyType());
192 282
193 EXPECT_FALSE(element->animatedPropertyTypeSupportsAddition()); 283 EXPECT_FALSE(element->animatedPropertyTypeSupportsAddition());
284
285 element->setAttributeName(SVGNames::hrefAttr);
286
287 // Sanity check that href was identified as a "string" attribute
288 EXPECT_EQ(AnimatedString, element->animatedPropertyType());
289
290 EXPECT_FALSE(element->animatedPropertyTypeSupportsAddition());
194 } 291 }
195 292
196 TEST( 293 TEST(
197 UnsafeSVGAttributeSanitizationTest, 294 UnsafeSVGAttributeSanitizationTest,
198 stripScriptingAttributes_animateElement) 295 stripScriptingAttributes_animateElement)
199 { 296 {
200 Vector<Attribute> attributes; 297 Vector<Attribute> attributes;
201 attributes.append(Attribute(XLinkNames::hrefAttr, "javascript:alert()")); 298 attributes.append(Attribute(XLinkNames::hrefAttr, "javascript:alert()"));
299 attributes.append(Attribute(SVGNames::hrefAttr, "javascript:alert()"));
202 attributes.append(Attribute(SVGNames::fromAttr, "/home")); 300 attributes.append(Attribute(SVGNames::fromAttr, "/home"));
203 attributes.append(Attribute(SVGNames::toAttr, "javascript:own3d()")); 301 attributes.append(Attribute(SVGNames::toAttr, "javascript:own3d()"));
204 302
205 RefPtrWillBeRawPtr<Document> document = Document::create(); 303 RefPtrWillBeRawPtr<Document> document = Document::create();
206 RefPtrWillBeRawPtr<Element> element = SVGAnimateElement::create(*document); 304 RefPtrWillBeRawPtr<Element> element = SVGAnimateElement::create(*document);
207 element->stripScriptingAttributes(attributes); 305 element->stripScriptingAttributes(attributes);
208 306
209 EXPECT_EQ(2ul, attributes.size()) << 307 EXPECT_EQ(3ul, attributes.size()) <<
210 "One of the attributes should have been stripped."; 308 "One of the attributes should have been stripped.";
211 EXPECT_EQ(XLinkNames::hrefAttr, attributes[0].name()) << 309 EXPECT_EQ(XLinkNames::hrefAttr, attributes[0].name()) <<
212 "The 'xlink:href' attribute should not have been stripped from " 310 "The 'xlink:href' attribute should not have been stripped from "
213 "<animate> because it is not a URL attribute of <animate>."; 311 "<animate> because it is not a URL attribute of <animate>.";
214 EXPECT_EQ(SVGNames::fromAttr, attributes[1].name()) << 312 EXPECT_EQ(SVGNames::hrefAttr, attributes[1].name()) <<
313 "The 'href' attribute should not have been stripped from "
314 "<animate> because it is not a URL attribute of <animate>.";
315 EXPECT_EQ(SVGNames::fromAttr, attributes[2].name()) <<
215 "The 'from' attribute should not have been strippef from <animate> " 316 "The 'from' attribute should not have been strippef from <animate> "
216 "because its value is innocuous."; 317 "because its value is innocuous.";
217 } 318 }
218 319
219 TEST( 320 TEST(
220 UnsafeSVGAttributeSanitizationTest, 321 UnsafeSVGAttributeSanitizationTest,
322 isJavaScriptURLAttribute_hrefContainingJavascriptURL)
323 {
324 Attribute attribute(SVGNames::hrefAttr, "javascript:alert()");
325 RefPtrWillBeRawPtr<Document> document = Document::create();
326 RefPtrWillBeRawPtr<Element> element = SVGAElement::create(*document);
327 EXPECT_TRUE(
328 element->isJavaScriptURLAttribute(attribute)) <<
329 "The 'a' element should identify an 'href' attribute with a "
330 "JavaScript URL value as a JavaScript URL attribute";
331 }
332
333 TEST(
334 UnsafeSVGAttributeSanitizationTest,
221 isJavaScriptURLAttribute_xlinkHrefContainingJavascriptURL) 335 isJavaScriptURLAttribute_xlinkHrefContainingJavascriptURL)
222 { 336 {
223 Attribute attribute(XLinkNames::hrefAttr, "javascript:alert()"); 337 Attribute attribute(XLinkNames::hrefAttr, "javascript:alert()");
224 RefPtrWillBeRawPtr<Document> document = Document::create(); 338 RefPtrWillBeRawPtr<Document> document = Document::create();
225 RefPtrWillBeRawPtr<Element> element = SVGAElement::create(*document); 339 RefPtrWillBeRawPtr<Element> element = SVGAElement::create(*document);
226 EXPECT_TRUE( 340 EXPECT_TRUE(
227 element->isJavaScriptURLAttribute(attribute)) << 341 element->isJavaScriptURLAttribute(attribute)) <<
228 "The 'a' element should identify an 'xlink:href' attribute with a " 342 "The 'a' element should identify an 'xlink:href' attribute with a "
229 "JavaScript URL value as a JavaScript URL attribute"; 343 "JavaScript URL value as a JavaScript URL attribute";
230 } 344 }
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
291 Attribute fineAttribute(SVGNames::fromAttr, "hello, world!"); 405 Attribute fineAttribute(SVGNames::fromAttr, "hello, world!");
292 RefPtrWillBeRawPtr<Document> document = Document::create(); 406 RefPtrWillBeRawPtr<Document> document = Document::create();
293 RefPtrWillBeRawPtr<Element> element = SVGSetElement::create(*document); 407 RefPtrWillBeRawPtr<Element> element = SVGSetElement::create(*document);
294 EXPECT_FALSE( 408 EXPECT_FALSE(
295 element->isSVGAnimationAttributeSettingJavaScriptURL(fineAttribute)) << 409 element->isSVGAnimationAttributeSettingJavaScriptURL(fineAttribute)) <<
296 "The animate element should not identify a 'from' attribute with an " 410 "The animate element should not identify a 'from' attribute with an "
297 "innocuous value as setting a JavaScript URL."; 411 "innocuous value as setting a JavaScript URL.";
298 } 412 }
299 413
300 } // namespace blink 414 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/svg/SVGUseElement.cpp ('k') | third_party/WebKit/Source/core/svg/animation/SVGSMILElement.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698