From 7c20ccbc73ffa5048b41d3ae383ac3cd4aa3c772 Mon Sep 17 00:00:00 2001 From: Jim Date: Tue, 20 Jan 2015 12:09:22 -0800 Subject: [PATCH] Document justification for dangerouslySetInnerHTML, fixes #2256 Conflicts: docs/_data/nav_tips.yml docs/tips/17-children-undefined.md --- _data/nav_tips.yml | 2 ++ docs/02.3-jsx-gotchas.md | 2 +- docs/ref-07-special-non-dom-attributes.md | 2 +- tips/17-children-undefined.md | 2 +- tips/18-use-react-with-other-libraries.md | 1 + tips/19--dangerouslySetInnerHTML.md | 24 +++++++++++++++++++++++ 6 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 tips/19--dangerouslySetInnerHTML.md diff --git a/_data/nav_tips.yml b/_data/nav_tips.yml index 992ba496..188a3ac2 100644 --- a/_data/nav_tips.yml +++ b/_data/nav_tips.yml @@ -36,3 +36,5 @@ title: this.props.children undefined - id: use-react-with-other-libraries title: Use React with Other Libraries + - id: dangerously-set-inner-html + title: Dangerously Set innerHTML diff --git a/docs/02.3-jsx-gotchas.md b/docs/02.3-jsx-gotchas.md index 9f444657..ddf06de2 100644 --- a/docs/02.3-jsx-gotchas.md +++ b/docs/02.3-jsx-gotchas.md @@ -46,7 +46,7 @@ You can use mixed arrays with strings and JSX elements.
{['First ', ·, ' Second']}
``` -As a last resort, you always have the ability to insert raw HTML. +As a last resort, you always have the ability to [insert raw HTML](/react/docs/dom-differences.html). ```javascript
diff --git a/docs/ref-07-special-non-dom-attributes.md b/docs/ref-07-special-non-dom-attributes.md index 38e3ce8e..f3fd90c1 100644 --- a/docs/ref-07-special-non-dom-attributes.md +++ b/docs/ref-07-special-non-dom-attributes.md @@ -10,4 +10,4 @@ Beside [DOM differences](/react/docs/dom-differences.html), React offers some at - `key`: an optional, unique identifier. When your component shuffles around during `render` passes, it might be destroyed and recreated due to the diff algorithm. Assigning it a key that persists makes sure the component stays. See more [here](/react/docs/multiple-components.html#dynamic-children). - `ref`: see [here](/react/docs/more-about-refs.html). -- `dangerouslySetInnerHTML`: takes an object with the key `__html` and a DOM string as value. This is mainly for cooperating with DOM string manipulation libraries. Refer to the last example on the front page. +- `dangerouslySetInnerHTML`: Provides the ability to insert raw HTML, mainly for cooperating with DOM string manipulation libraries. See more [here](/react/tips/dangerously-set-inner-html.html). diff --git a/tips/17-children-undefined.md b/tips/17-children-undefined.md index cfbc656d..5eaad318 100644 --- a/tips/17-children-undefined.md +++ b/tips/17-children-undefined.md @@ -25,4 +25,4 @@ var App = React.createClass({ React.render(, mountNode); ``` -To access your own subcomponents (the `span`s), place [refs](http://facebook.github.io/react/docs/more-about-refs.html) on them. +For a more sophisticated example, refer to the last example on the [front page](/). diff --git a/tips/18-use-react-with-other-libraries.md b/tips/18-use-react-with-other-libraries.md index 43299deb..094f2bdc 100644 --- a/tips/18-use-react-with-other-libraries.md +++ b/tips/18-use-react-with-other-libraries.md @@ -4,6 +4,7 @@ title: Use React with Other Libraries layout: tips permalink: use-react-with-other-libraries.html prev: children-undefined.html +next: dangerously-set-inner-html.html --- You don't have to go full React. The component [lifecycle events](/react/docs/component-specs.html#lifecycle-methods), especially `componentDidMount` and `componentDidUpdate`, are good places to put your other libraries' logic. diff --git a/tips/19--dangerouslySetInnerHTML.md b/tips/19--dangerouslySetInnerHTML.md new file mode 100644 index 00000000..27bb4aae --- /dev/null +++ b/tips/19--dangerouslySetInnerHTML.md @@ -0,0 +1,24 @@ +--- +id: dangerously-set-inner-html +title: Dangerously Set innerHTML +layout: tips +permalink: dangerously-set-inner-html.html +prev: children-undefined.html +--- + +Improper use of the `innerHTML` can open you up to a [cross-site scripting (XSS)](http://en.wikipedia.org/wiki/Cross-site_scripting) attack. Sanitizing user input for display is notoriously error-prone, and failure to properly sanitize is one of the [leading causes of web vulnerabilities](http://owasptop10.googlecode.com/files/OWASP%20Top%2010%20-%202013.pdf) on the internet. + +Our design philosophy is that it should be “easy” to make things safe, and developers should explicitly state their intent when performing “unsafe” operations. The prop name `dangerouslySetInnerHTML` is intentionally chosen to be frightening, and the prop value (an object instead of a string) can be used to indicate sanitized data. + +After fully understanding the security ramifications and properly sanitizing the data, create a new object containing only the key `__html` and your sanitized data as the value. Here is an example using the JSX syntax: + +```js +function createMarkup() { return {__html: 'First · Second'}; }; +
+``` + +The point being that if you unintentionally do say `
` it will not be rendered because `getUsername()` would return a plain `string` and not a `{__html: ''}` object. The intent behind the `{__html:...}` syntax is that it be considered a "type/taint" of sorts. Sanitized data can be returned from a function using this wrapper object, and this marked data can subsequently be passed into `dangerouslySetInnerHTML`. For this reason, we recommend against writing code of the form `
`. + +This functionality is mainly provided for cooperation with DOM string manipulation libraries, so the HTML provided must be well-formed (ie., pass XML validation). + +For a more complete usage example, refer to the last example on the [front page](/).