Security for React Apps
Tags: react, javascript, security, webdev
Published: 2022-03-14 21:12:54

## Default XSS Protection with Data Binding

Use default data binding with curly braces `{}` and React will automatically escape values to protect against **XSS attacks**. Note that this protection **only occurs when rendering textContent** and not when rendering HTML attributes.

- Use **JSX** data binding syntax `{}` to place data in your elements. Ex. `<div>{data}</div>`.
- Avoid dynamic attribute values without custom validation. Don’t use `...`

---

## Dangerous URLs

URLs can contain **dynamic script** content via javascript: protocol urls. Validate URLs before use.

- Use validation to **assure your links are http or https** to avoid javascript: URL based script injection. Achieve URL validation using a native URL parsing function then match the parsed
protocol property to an allow list.

```
function validateURL(url) {
	const parsed = new URL(url)
	return ['https:', 'http:'].includes(parsed.protocol)
}
<a href={validateURL(url) ? url : ''}>This is a link!</a>
```

---

## Rendering HTML

It is possible to insert HTML directly into rendered **DOM** nodes using `dangerouslySetInnerHTML`. Any content inserted this way must be sanitized beforehand.

- Use a sanitization library like **DOMPurify** on any values before placing them into the `dangerouslySetInnerHTML` prop.

```
import purify from "dompurify";

<div dangerouslySetInnerHTML={{__html:purify.sanitize(data)}} />
```

---

## Direct DOM Access

Accessing the DOM to **inject content into DOM nodes** directly should be avoided. Use `dangerouslySetInnerHTML` if you must **inject HTML and sanitize it** before injecting it using DOMPurify

- Avoid using refs and findDomNode() to access rendered DOM elements to directly inject content via innerHTML and similar properties and methods.

---

## Server-side Rendering

Data binding will provide **automatic content escaping** when using server-side rendering functions like `ReactDOMServer.renderToString()` and `ReactDOMServer.renderToStaticMarkup()`.

- Avoid concatenating strings on to the output of `renderToString()` and `renderToStaticMarkup()` before sending the strings **to the client for hydration** or rendering.

---

## Known Vulnerabilities in Dependencies

Some versions of third-party components **might contain security issues**. Check your dependencies and **update when better versions** become available.

- Use a tool like the free **Snyk** cli to check for vulnerabilities.
- Automatically fix vulnerabilities with **Snyk** by integrating **with your source code management** system to receive automated fixes.

`$ npx snyk test`

---

## JSON State

It is common to send JSON data along with server-side rendered React pages. Always escape < characters with a benign value to **avoid injection attacks**.

- Avoid unescaped HTML **significant values** in JSON state objects.

```
<script>
//WARNING: See the following for security issues around embedding JSON in HTML:
//[https://redux.js.org/recipes/server-rendering/#security-considerations](https://redux.js.org/recipes/server-rendering/#security-considerations)
  window.PRELOADED_STATE = ${JSON.stringify(preloadedState).replace(/</g,'\\u003c')}
</script>
```

---

## Vulnerable Versions of React

The React library has had a **few high severity vulnerabilities** in the past, so it is a good idea to stay **up-to-date with the latest version**.

- Avoid **vulnerable versions of the react** and react-dom by verifying that you are on the latest version using npm outdated to see the **latest versions**.
- Use **Snyk** to automatically update to new versions when vulnerabilities exist in the versions you are using.

---

## Linters

Install Linters configurations and plugins that will **automatically detect security issues** in your code and offer remediation advice.

- Use the **ESLint React security config** to detect security issues in our code base (**Install vscode Snyk extension**).
- Configure a **pre-commit hook** that fails when security related linter issues are detected using a library like **husky**.

---

## Dangerous Library Code

Library code is often used to perform dangerous operations like directly inserting HTML into the DOM. Review library code manually or with linters to detect unsafe usage of React’s security mechanisms.

- Avoid libraries that do use `dangerouslySetInnerHTML`, `innerHTML`, unvalidated URLs or other unsafe patterns.
- Use security linters on your **node_modules** folder to detect **unsafe patterns** in your library code.