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

Side by Side Diff: tools/dom/src/Validators.dart

Issue 1077813002: Check for DOM clobbering attacks in sanitizing/node validation (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 8 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
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of dart.dom.html; 5 part of dart.dom.html;
6 6
7 7
8 /** 8 /**
9 * Interface used to validate that only accepted elements and attributes are 9 * Interface used to validate that only accepted elements and attributes are
10 * allowed while parsing HTML strings into DOM nodes. 10 * allowed while parsing HTML strings into DOM nodes.
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
138 138
139 /** 139 /**
140 * Standard tree sanitizer which validates a node tree against the provided 140 * Standard tree sanitizer which validates a node tree against the provided
141 * validator and removes any nodes or attributes which are not allowed. 141 * validator and removes any nodes or attributes which are not allowed.
142 */ 142 */
143 class _ValidatingTreeSanitizer implements NodeTreeSanitizer { 143 class _ValidatingTreeSanitizer implements NodeTreeSanitizer {
144 NodeValidator validator; 144 NodeValidator validator;
145 _ValidatingTreeSanitizer(this.validator) {} 145 _ValidatingTreeSanitizer(this.validator) {}
146 146
147 void sanitizeTree(Node node) { 147 void sanitizeTree(Node node) {
148 void walk(Node node) { 148 void walk(Node node, Node parent) {
149 sanitizeNode(node); 149 sanitizeNode(node, parent);
150 150
151 var child = node.lastChild; 151 var child = node.lastChild;
152 while (child != null) { 152 while (child != null) {
153 // Child may be removed during the walk. 153 // Child may be removed during the walk.
154 var nextChild = child.previousNode; 154 var nextChild = child.previousNode;
155 walk(child); 155 walk(child, node);
156 child = nextChild; 156 child = nextChild;
157 } 157 }
158 } 158 }
159 walk(node); 159 walk(node, null);
160 } 160 }
161 161
162 void sanitizeNode(Node node) { 162 /// Aggressively try to remove node.
163 void _removeNode(Node node, Node parent) {
164 // If we have the parent, it's presumably already passed more sanitization o r
165 // is the fragment, so ask it to remove the child. And if that fails try to
166 // set the outer html.
167 if (parent == null) {
168 node.remove();
169 } else {
170 try {
171 parent._removeChild(node);
172 } catch (e) {
173 node.outerHtml = '';
174 }
175 }
176 }
177
178 void sanitizeNode(Node node, Node parent) {
163 switch (node.nodeType) { 179 switch (node.nodeType) {
164 case Node.ELEMENT_NODE: 180 case Node.ELEMENT_NODE:
165 Element element = node; 181 Element element = node;
182 if (element._hasCorruptedAttributes) {
183 window.console.warn('Removing element due to corrupted attributes on < ${element}>');
184 _removeNode(node, parent);
185 break;
186 }
166 var attrs = element.attributes; 187 var attrs = element.attributes;
167 if (!validator.allowsElement(element)) { 188 if (!validator.allowsElement(element)) {
168 window.console.warn( 189 window.console.warn(
169 'Removing disallowed element <${element.tagName}>'); 190 'Removing disallowed element <${element.tagName}>');
170 element.remove(); 191 _removeNode(node, parent);
171 break; 192 break;
172 } 193 }
173 194
174 var isAttr = attrs['is']; 195 var isAttr = attrs['is'];
175 if (isAttr != null) { 196 if (isAttr != null) {
176 if (!validator.allowsAttribute(element, 'is', isAttr)) { 197 if (!validator.allowsAttribute(element, 'is', isAttr)) {
177 window.console.warn('Removing disallowed type extension ' 198 window.console.warn('Removing disallowed type extension '
178 '<${element.tagName} is="$isAttr">'); 199 '<${element.tagName} is="$isAttr">');
179 element.remove(); 200 _removeNode(node, parent);
180 break; 201 break;
181 } 202 }
182 } 203 }
183 204
184 // TODO(blois): Need to be able to get all attributes, irrespective of 205 // TODO(blois): Need to be able to get all attributes, irrespective of
185 // XMLNS. 206 // XMLNS.
186 var keys = attrs.keys.toList(); 207 var keys = attrs.keys.toList();
187 for (var i = attrs.length - 1; i >= 0; --i) { 208 for (var i = attrs.length - 1; i >= 0; --i) {
188 var name = keys[i]; 209 var name = keys[i];
189 if (!validator.allowsAttribute(element, name.toLowerCase(), 210 if (!validator.allowsAttribute(element, name.toLowerCase(),
190 attrs[name])) { 211 attrs[name])) {
191 window.console.warn('Removing disallowed attribute ' 212 window.console.warn('Removing disallowed attribute '
192 '<${element.tagName} $name="${attrs[name]}">'); 213 '<${element.tagName} $name="${attrs[name]}">');
193 attrs.remove(name); 214 attrs.remove(name);
194 } 215 }
195 } 216 }
196 217
197 if (element is TemplateElement) { 218 if (element is TemplateElement) {
198 TemplateElement template = element; 219 TemplateElement template = element;
199 sanitizeTree(template.content); 220 sanitizeTree(template.content);
200 } 221 }
201 break; 222 break;
202 case Node.COMMENT_NODE: 223 case Node.COMMENT_NODE:
203 case Node.DOCUMENT_FRAGMENT_NODE: 224 case Node.DOCUMENT_FRAGMENT_NODE:
204 case Node.TEXT_NODE: 225 case Node.TEXT_NODE:
205 case Node.CDATA_SECTION_NODE: 226 case Node.CDATA_SECTION_NODE:
206 break; 227 break;
207 default: 228 default:
208 node.remove(); 229 _removeNode(node, parent);
209 } 230 }
210 } 231 }
211 } 232 }
OLDNEW
« no previous file with comments | « tests/html/node_validator_test.dart ('k') | tools/dom/templates/html/impl/impl_Element.darttemplate » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698