@samitouri / QOS-React-2 / commits / a4e923b7fc

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 });