Sanitize the string tag passed to DOM components
Because we're using innerHTML to generate DOM Elements, we need to make sure that the tag is sane and doesn't try to do injection. This wouldn't be an issue if we used document.createElement instead.
Sebastian Markbage committed
Oct 9, 2014 at 13:55 UTC
a4e923b7fcc0313a0894740ba0ef60ba12ba9573
2 files changed
+40
-1
src/browser/ui/ReactDOMComponent.js
+16
-1
@@ -121,6 +121,21 @@ var omittedCloseTags = {
121
// NOTE: menuitem's close tag should be omitted, but that causes problems.
122
};
123
124
+// We accept any tag to be rendered but since this gets injected into abitrary
125
+// HTML, we want to make sure that it's a safe tag.
126
+// http://www.w3.org/TR/REC-xml/#NT-Name
127
+
128
+var VALID_TAG_REGEX = /^[a-zA-Z][a-zA-Z:_\.\-\d]*$/; // Simplified subset
129
+var validatedTagCache = {};
130
+var hasOwnProperty = {}.hasOwnProperty;
131
+
132
+function validateDangerousTag(tag) {
133
+ if (!hasOwnProperty.call(validatedTagCache, tag)) {
134
+ invariant(VALID_TAG_REGEX.test(tag), 'Invalid tag: %s', tag);
135
+ validatedTagCache[tag] = true;
136
+ }
137
+}
138
+
139
/**
140
* Creates a new React class that is idempotent and capable of containing other
141
* React components. It accepts event listeners and DOM properties that are
@@ -137,7 +152,7 @@ var omittedCloseTags = {
152
* @extends ReactMultiChild
153
*/
154
function ReactDOMComponent(tag) {
140
- // TODO: DANGEROUS this tag should be sanitized.
155
+ validateDangerousTag(tag);
156
this._tag = tag;
157
this.tagName = tag.toUpperCase();
158
}
src/browser/ui/__tests__/ReactDOMComponent-test.js
+24
@@ -453,4 +453,28 @@ describe('ReactDOMComponent', function() {
453
});
454
});
455
456
+ describe('tag sanitization', function() {
457
+ it('should throw when an invalid tag name is used', () => {
458
+ var React = require('React');
459
+ var ReactTestUtils = require('ReactTestUtils');
460
+ var hackzor = React.createElement('script tag');
461
+ expect(
462
+ () => ReactTestUtils.renderIntoDocument(hackzor)
463
+ ).toThrow(
464
+ 'Invariant Violation: Invalid tag: script tag'
465
+ );
466
+ });
467
+
468
+ it('should throw when an attack vector is used', () => {
469
+ var React = require('React');
470
+ var ReactTestUtils = require('ReactTestUtils');
471
+ var hackzor = React.createElement('div><img /><div');
472
+ expect(
473
+ () => ReactTestUtils.renderIntoDocument(hackzor)
474
+ ).toThrow(
475
+ 'Invariant Violation: Invalid tag: div><img /><div'
476
+ );
477
+ });
478
+
479
+ });
480
});