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

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

Issue 1171223004: Sanitize SVG animation attributes which could set JavaScript URL values. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 5 years, 6 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 | Annotate | Revision Log
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "config.h"
6 // FIXME(dominicc): Poor confused check-webkit-style demands Attribute.h here.
7 #include "core/dom/Attribute.h"
8
9 #include "core/HTMLNames.h"
10 #include "core/SVGNames.h"
11 #include "core/XLinkNames.h"
12 #include "core/clipboard/Pasteboard.h"
13 #include "core/dom/QualifiedName.h"
14 #include "core/editing/Editor.h"
15 #include "core/editing/SelectionType.h"
16 #include "core/editing/VisibleSelection.h"
17 #include "core/html/HTMLElement.h"
18 #include "core/svg/SVGAElement.h"
19 #include "core/svg/SVGAnimateElement.h"
20 #include "core/svg/SVGDiscardElement.h"
21 #include "core/svg/SVGSetElement.h"
22 #include "core/svg/animation/SVGSMILElement.h"
23 #include "core/svg/properties/SVGPropertyInfo.h"
24 #include "core/testing/DummyPageHolder.h"
25 #include "platform/geometry/IntSize.h"
26 #include "platform/weborigin/KURL.h"
27 #include "wtf/Vector.h"
28 #include "wtf/text/AtomicString.h"
29 #include "wtf/text/WTFString.h"
30 #include <gtest/gtest.h>
31
32 namespace blink {
33
34 // The following SVG elements, although related to animation, cannot
35 // set JavaScript URLs:
36 //
37 // - 'discard' can only remove elements, not set their attributes
38 // - 'animateMotion' does not use attribute name and produces floats
39 // - 'animateTransform' can only animate transform lists
40
41 // Pastes htmlToPaste into the body of pageHolder's document, and
42 // returns the new content of the body.
43 String contentAfterPastingHTML(
44 DummyPageHolder* pageHolder,
45 const char* htmlToPaste)
46 {
47 LocalFrame& frame = pageHolder->frame();
48 HTMLElement* body = pageHolder->document().body();
49
50 // Make the body editable, and put the caret in it.
51 body->setAttribute(HTMLNames::contenteditableAttr, "true");
52 frame.selection().setSelection(VisibleSelection::selectionFromContentsOfNode (body));
53 EXPECT_EQ(CaretSelection, frame.selection().selectionType());
54 EXPECT_TRUE(frame.selection().isContentEditable()) <<
55 "We should be pasting into something editable.";
56
57 Pasteboard pasteboard;
58 pasteboard.writeHTML(htmlToPaste, blankURL(), "", false);
dcheng 2015/06/10 09:35:28 Can you remind me how this works for the Blink uni
59 frame.editor().pasteWithPasteboard(&pasteboard);
dcheng 2015/06/10 09:35:28 How about frame.editor().execCommand("paste") to a
60
61 return body->innerHTML();
62 }
63
64 // Integration tests.
65 //
66 // Other sanitization integration tests are layout tests that use
67 // document.execCommand('Copy') to source content that they later
68 // paste. However SVG animation elements are not serialized when
69 // copying, which means we can't test sanitizing these attributes in
70 // layout tests: there is nowhere to source the unsafe content from.
71
72 TEST(UnsafeSVGAttributeSanitizationTest, pasteAnchor_javaScriptHrefIsStripped)
73 {
74 OwnPtr<DummyPageHolder> pageHolder = DummyPageHolder::create(IntSize(1, 1));
75 const char* unsafeContent =
dcheng 2015/06/10 09:35:28 Nit: const char* unsafeContent is actually a mutab
Tom Sepez 2015/06/10 17:29:02 nit: Don't you want static const char unsafeConten
76 "<svg xmlns='http://www.w3.org/2000/svg' "
77 " xmlns:xlink='http://www.w3.org/1999/xlink'"
78 " width='1cm' height='1cm'>"
79 " <a xlink:href='javascript:alert()'></a>"
80 "</svg>";
81 String sanitizedContent =
82 contentAfterPastingHTML(pageHolder.get(), unsafeContent);
83
84 EXPECT_TRUE(sanitizedContent.contains("</a>")) <<
85 "We should have pasted *something*; the document is: " <<
86 sanitizedContent.utf8().data();
87 EXPECT_FALSE(sanitizedContent.contains("javascript:")) <<
88 "The JavaScript URL is unsafe and should have been stripped; "
89 "instead: " <<
90 sanitizedContent.utf8().data();
91 }
92
93 TEST(
94 UnsafeSVGAttributeSanitizationTest,
Tom Sepez 2015/06/10 17:29:02 Nit: funny indentation? I'd expect UnsafeSVGAttrib
95 pasteAnimatedAnchor_javaScriptHrefIsStripped)
96 {
97 OwnPtr<DummyPageHolder> pageHolder = DummyPageHolder::create(IntSize(1, 1));
98 const char* unsafeContent =
99 "<svg xmlns='http://www.w3.org/2000/svg' "
100 " xmlns:xlink='http://www.w3.org/1999/xlink'"
101 " width='1cm' height='1cm'>"
102 " <a xlink:href='https://www.google.com/'>"
103 " <animate xmlns:ng='http://www.w3.org/1999/xlink' "
104 " attributeName='ng:href' values='evil;javascript:alert()'>"
Tom Sepez 2015/06/10 17:29:02 nit: How about writing JavASCRipT in mixed case in
105 " </a>"
106 "</svg>";
107 String sanitizedContent =
108 contentAfterPastingHTML(pageHolder.get(), unsafeContent);
109
110 EXPECT_TRUE(sanitizedContent.contains("<a xlink:href=\"https://www.goo")) <<
111 "We should have pasted *something*; the document is: " <<
112 sanitizedContent.utf8().data();
113 EXPECT_FALSE(sanitizedContent.contains("javascript:")) <<
114 "The JavaScript URL is unsafe and should have been stripped; "
115 "instead: " <<
116 sanitizedContent.utf8().data();
117 }
118
119 // Unit tests
120
121 // stripScriptingAttributes inspects animation attributes for
122 // javascript: URLs. This check could be defeated if strings supported
123 // addition. If this test starts failing you must strengthen
124 // Element::stripScriptingAttributes perhaps to strip all
125 // isSVGAttributeValueAnimatingAttribute attributes.
126 TEST(UnsafeSVGAttributeSanitizationTest, stringsShouldNotSupportAddition)
127 {
128 RefPtrWillBeRawPtr<Document> document = Document::create();
129 RefPtrWillBeRawPtr<SVGElement> target = SVGAElement::create(*document);
130 RefPtrWillBeRawPtr<SVGAnimateElement> element = SVGAnimateElement::create(*d ocument);
131 element->setTargetElement(target.get());
132 element->setAttributeName(XLinkNames::hrefAttr);
133
134 // Sanity check that xlink:href was identified as a "string" attribute
135 EXPECT_EQ(AnimatedString, element->animatedPropertyType());
136
137 EXPECT_FALSE(element->animatedPropertyTypeSupportsAddition());
138 }
139
140 TEST(
141 UnsafeSVGAttributeSanitizationTest,
142 stripScriptingAttributes_stripsHrefContainingJavascriptURL)
143 {
144 Vector<Attribute> attributes;
145 attributes.append(Attribute(XLinkNames::hrefAttr, "javascript:alert()"));
146
147 RefPtrWillBeRawPtr<Document> document = Document::create();
148 RefPtrWillBeRawPtr<Element> element = SVGAElement::create(*document);
149 element->stripScriptingAttributes(attributes);
150
151 EXPECT_EQ(0ul, attributes.size()) <<
152 "stripScriptingAttributes should strip an 'xlink:href' attribute with "
153 "a JavaScript URL value.";
154 }
155
156 TEST(
157 UnsafeSVGAttributeSanitizationTest,
158 stripScriptingAttributes_stripsHrefContainingJavascriptURL_alternatePrefix)
159 {
160 Vector<Attribute> attributes;
161 QualifiedName hrefAlternatePrefix(
162 "foo", "href", XLinkNames::xlinkNamespaceURI);
163 attributes.append(Attribute(hrefAlternatePrefix, "javascript:alert()"));
164
165 RefPtrWillBeRawPtr<Document> document = Document::create();
166 RefPtrWillBeRawPtr<Element> element = SVGAElement::create(*document);
167 element->stripScriptingAttributes(attributes);
168
169 EXPECT_EQ(0ul, attributes.size()) <<
170 "stripScriptingAttributes should strip an XLink 'href' attribute with "
171 "a JavaScript URL value, even if the attribute doesn't use the typical "
172 "'xlink' prefix.";
173 }
174
175 TEST(
176 UnsafeSVGAttributeSanitizationTest,
177 stripScriptingAttributes_stripsAnimationsThatSetJavascriptURLs_from)
178 {
179 Vector<Attribute> attributes;
180 attributes.append(Attribute(SVGNames::fromAttr, "javascript:alert()"));
181
182 RefPtrWillBeRawPtr<Document> document = Document::create();
183 RefPtrWillBeRawPtr<Element> element = SVGAnimateElement::create(*document);
184 element->stripScriptingAttributes(attributes);
185
186 EXPECT_EQ(0ul, attributes.size()) <<
187 "stripScriptingAttributes should strip an animation 'from' attribute "
188 "with a JavaScript URL value.";
189 }
190
191 TEST(
192 UnsafeSVGAttributeSanitizationTest,
193 stripScriptingAttributes_stripsAnimationsThatSetJavascriptURLs_to)
194 {
195 Vector<Attribute> attributes;
196 attributes.append(Attribute(SVGNames::toAttr, "javascript:window.close()"));
197
198 RefPtrWillBeRawPtr<Document> document = Document::create();
199 RefPtrWillBeRawPtr<Element> element = SVGSetElement::create(*document);
200 element->stripScriptingAttributes(attributes);
201
202 EXPECT_EQ(0ul, attributes.size()) <<
203 "stripScriptingAttributes should strip an animation 'to' attribute "
204 "with a JavaScript URL value.";
205 }
206
207 TEST(
208 UnsafeSVGAttributeSanitizationTest,
209 stripScriptingAttributes_stripsAnimationsThatSetJavascriptURLs_values)
210 {
211 Vector<Attribute> attributes;
212 attributes.append(
213 Attribute(SVGNames::valuesAttr, "evil; javascript:confirm()"));
214
215 RefPtrWillBeRawPtr<Document> document = Document::create();
216 RefPtrWillBeRawPtr<Element> element = SVGAnimateElement::create(*document);
217 element = SVGAnimateElement::create(*document);
218 element->stripScriptingAttributes(attributes);
219
220 EXPECT_EQ(0ul, attributes.size()) <<
221 "stripScriptingAttributes should strip an animation 'values' attribute "
222 "which contains a JavaScript URL value.";
223 }
224
225 TEST(
226 UnsafeSVGAttributeSanitizationTest,
227 stripScriptingAttributes_doesNotStripInnocuousAnimationAttributes)
228 {
229 Vector<Attribute> attributes;
230 attributes.append(Attribute(SVGNames::fromAttr, "hello, world!"));
231
232 RefPtrWillBeRawPtr<Document> document = Document::create();
233 RefPtrWillBeRawPtr<Element> element = SVGSetElement::create(*document);
234 element->stripScriptingAttributes(attributes);
235
236 EXPECT_EQ(1ul, attributes.size()) <<
237 "stripScriptingAttributes should not strip an animation 'from' "
238 "attribute with a non-JavaScript URL value.";
239 }
240
241 TEST(
242 UnsafeSVGAttributeSanitizationTest,
243 stripScriptingAttributes_doesNotStripAnimationAttributesInOtherContexts)
244 {
245 Vector<Attribute> attributes;
246 attributes.append(Attribute(SVGNames::fromAttr, "javascript:alert()"));
247
248 RefPtrWillBeRawPtr<Document> document = Document::create();
249 RefPtrWillBeRawPtr<Element> element = SVGDiscardElement::create(*document);
250 element->stripScriptingAttributes(attributes);
251
252 EXPECT_EQ(1ul, attributes.size()) <<
253 "stripScriptingAttributes should not strip a 'from' attribute used on "
254 "a non-animation element.";
255 }
256
257 } // namespace blink
OLDNEW
« Source/core/svg/SVGAnimateElement.cpp ('K') | « Source/core/svg/SVGAnimationElement.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698