Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docs/security in gatsby #22395

Merged
merged 41 commits into from
Mar 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
f5434f0
docs(security-in-gatsby): removing stub
luizcieslak Mar 19, 2020
e1afad0
docs(security-in-gatsby): add markdown with topics
luizcieslak Mar 19, 2020
b1e2b7d
docs(security-in-gatsby): fix typo
luizcieslak Mar 19, 2020
6f7c5c2
docs(security-in-gatsby): fix typo
luizcieslak Mar 20, 2020
a0e707a
docs(security-in-gatsby): more declarative link to gatsby-plugin-csp
luizcieslak Mar 20, 2020
06ad16d
docs(security-in-gatsby): more declarative link to CSP's can-i-use
luizcieslak Mar 20, 2020
a2a85e7
docs(security-in-gatsby): mention html parsers
luizcieslak Mar 20, 2020
b271cb6
docs(security-in-gatsby): add yarn audit alternative
luizcieslak Mar 20, 2020
c26b54c
docs(security-in-gatsby): expand more in others plugins
luizcieslak Mar 20, 2020
f90037c
docs(security-in-gatsby): links for 3 party script
luizcieslak Mar 20, 2020
fcdabee
docs(security-in-gatsby): add same-site cookies info
luizcieslak Mar 20, 2020
664d376
docs(security-in-gatsby): add web dev resource
luizcieslak Mar 20, 2020
8c838da
docs(security-in-gatsby): add key security section
luizcieslak Mar 20, 2020
b15df2a
docs(security-in-gatsby): using relative internal links
luizcieslak Mar 20, 2020
9c3abbe
docs(security-in-gatsby): fix csrf token section
luizcieslak Mar 22, 2020
9dade72
docs(security-in-gatsby): add more other resources
luizcieslak Mar 22, 2020
7339fa4
docs(security-in-gatsby): fix typo
luizcieslak Mar 22, 2020
194c7d8
docs(security-in-gatsby): fix typo
luizcieslak Mar 22, 2020
344d2fd
docs(security-in-gatsby): fix typo
luizcieslak Mar 22, 2020
1e52d47
docs(security-in-gatsby): cookies are not send w/ SameSite directive
luizcieslak Mar 22, 2020
88039d3
Update docs/docs/security-in-gatsby.md
luizcieslak Mar 23, 2020
5c12797
Update docs/docs/security-in-gatsby.md
luizcieslak Mar 23, 2020
d1481fa
Update docs/docs/security-in-gatsby.md
luizcieslak Mar 23, 2020
deb6aaa
Update docs/docs/security-in-gatsby.md
luizcieslak Mar 23, 2020
cf87593
Update docs/docs/security-in-gatsby.md
luizcieslak Mar 23, 2020
938df61
Update docs/docs/security-in-gatsby.md
luizcieslak Mar 26, 2020
77cd189
Update docs/docs/security-in-gatsby.md
luizcieslak Mar 26, 2020
7aa4da9
Update docs/docs/security-in-gatsby.md
luizcieslak Mar 26, 2020
d7fe95a
Update docs/docs/security-in-gatsby.md
luizcieslak Mar 26, 2020
090097b
Update docs/docs/security-in-gatsby.md
luizcieslak Mar 26, 2020
406837e
Apply suggestions from code review
luizcieslak Mar 26, 2020
3b81651
Apply suggestions from code review
luizcieslak Mar 27, 2020
1640a70
Update docs/docs/security-in-gatsby.md
luizcieslak Mar 27, 2020
52e4265
fix typo
luizcieslak Mar 27, 2020
aad2dcb
Merge remote-tracking branch 'origin/docs/security-in-gatsby' into do…
luizcieslak Mar 27, 2020
65a3a41
Apply suggestions from code review
luizcieslak Mar 27, 2020
84238b6
Apply suggestions from code review
luizcieslak Mar 27, 2020
d37dc36
Apply suggestions from code review
luizcieslak Mar 30, 2020
d315812
add text type in cookies code snipper
luizcieslak Mar 30, 2020
95acf5c
Minor grammer, remove quote indication
Mar 30, 2020
820047c
Merge remote-tracking branch 'upstream/master' into docs/security-in-…
Mar 30, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
161 changes: 157 additions & 4 deletions docs/docs/security-in-gatsby.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,162 @@
---
title: Security in Gatsby
issue: https://github.com/gatsbyjs/gatsby/issues/13305
---

This is a stub. Help our community expand it.
By taking advantage of the benefits of static content, Gatsby inherits several security principles. However, even with this, your users can be exposed to malicious attacks. Read on for further information on potential attack vectors and how you could prevent them.

Please use the [Gatsby Style Guide](/contributing/gatsby-style-guide/) to ensure your
pull request gets accepted.
## Cross-Site Scripting (XSS)

Cross-Site Scripting is a type of attack that injects a script or an unexpected link to another site into the client side of the application.

JSX elements automatically escape HTML tags by design. See the following example:

```js
// highlight-next-line
const username = `<script src='https://path/to/badness.js'></script>`

const User = () => <p> hello {username}</p>
```

When you try to inject the JSX element above, it will render `hello <script src='https://path/to/badness.js'></script>` as a string inside the `p` tag.

On the other hand, fields in your application may need to render inner HTML tags, such as a content field in a blog or a comment in a comments section, that are built into rich-text editors.

In order to render those HTML tags you need to use an HTML parser (e.g. [html-react-parser](https://github.com/remarkablemark/html-react-parser)) or the `dangerouslySetInnerHTML` prop, like so:

```js
const CommentRenderer = comment => (
// highlight-next-line
<p dangerouslySetInnerHTML={{ __html: comment }} />
) // dangerous indeed.
```

luizcieslak marked this conversation as resolved.
Show resolved Hide resolved
That is when you expose your application to XSS attacks.

### How can you prevent cross-site scripting?

The most straightforward way to prevent a XSS attack is to sanitize the innerHTML string before dangerously setting it. Fortunately, there are npm packages that can accomplish this; packages like [sanitize-html](https://www.npmjs.com/package/sanitize-html) and [DOMPurify](https://github.com/cure53/DOMPurify).

## Cross-Site Request Forgery (CSRF)

Cross-Site request forgery is a type of exploit that deceives the browser into executing unauthorized actions. By default, in any request made, the browser automatically appends any stored cookies of the destination domain. Combining this with a crafted request, a malicious website can read and write data without the user's action or knowledge.

For example, assume that the comments in your blog are sent in a form similar to this one:

```html
<form action="http://mywebsite.com/blog/addcomment" method="POST">
<input type="text" name="comment" />
<input type="submit" />
</form>
```

A malicious website could inspect your site and copy this snippet to theirs. If the user is logged in, the associated cookies are sent with the form and the server cannot distinguish the origin of it. Even worse, the form could be sent when the page loads with information you don't control:

```js
// highlight-next-line
<body onload="document.csrf.submit()">
<!-- ... -->
<form action="http://mywebsite.com/blog/addcomment" method="POST" name="csrf">
// highlight-next-line
<input type="hidden" name="comment" value="Hey visit http://maliciouswebsite.com, it's pretty nice" />
<input type="submit" />
</form>
```

### How can you prevent cross-site request forgery?

#### Don't use GET requests to modify data

Actions that do not simply read data should be handled in a POST request. In the example above, if the `/blog/addcomment` endpoint accepts a GET request, the CSRF attack can be done using an `<img />` tag:

```html
<img src="http://mywebsite.com/blog/addcomment?comment=unwanted%20comment" />
```

#### CSRF Tokens

If you want to protect a page your server will provide an encrypted, hard to guess **token**. That token is tied to a user's session and must be included in every POST request. See the following example:

```js
<form action="http://mywebsite.com/blog/addcoment" method="POST">
<input type="text" name="comment" />
// highlight-next-line
<input type="hidden" name="token" value="SU9J3tMoT1w5q6uJ1VMXaaf9UXzLvyNd" />
<input type="submit" />
</form>
```

When the form is sent, the server will compare the token received with the stored token and block the action if they are not the same. Make sure that malicious websites don't have access to the CSRF token by using [HTTP Access Control](https://developer.mozilla.org/pt-BR/docs/Web/HTTP/Headers/Access-Control-Allow-Origin).

#### Same-Site Cookies Attribute

This cookie attribute is targeted to prevent CSRF attacks. If you need to create a cookie in your application, make sure to protect them by using this attribute, that could be of `Strict` or `Lax` type:

```text
Set-Cookie: example=1; SameSite=Strict
```

Using the `SameSite` attribute allows the server to make sure that the cookies are not being sent by a **cross-site** domain request.
Check out [MDN Docs](https://developer.mozilla.org/pt-BR/docs/Web/HTTP/Headers/Set-Cookie) for more information on configuring a cookie. You will also want to note current browser support which is available on the [Can I Use page](https://caniuse.com/#feat=same-site-cookie-attribute).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe needs an example. not totally understanding how/why this works.

Copy link
Contributor Author

@luizcieslak luizcieslak Mar 22, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, totally. I add a more clear example.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this is still outstanding?

This cookie attribute is not a replacement for a CSRF Token (and vice-versa). They can work together as security layers in your website. Otherwise, a Cross-Site Scripting attack can be used to defeat these CSRF mitigation techniques. Check out [OWASP CSRF prevention cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#samesite-cookie-attribute) for more information.

## Third-party Scripts

Some third-party scripts like Google Tag Manager give you the ability to [add arbitrary JavaScript](https://support.google.com/tagmanager/answer/6107167) to your site. This helps integrate third-party tools but can be misused to inject malicious code. To avoid this, be sure to [control access](https://support.google.com/tagmanager/answer/6107011) to these services.

## Check Your Dependencies

In your Gatsby project, you are going to have some dependencies that get stored in `node_modules/`. Therefore, it is important to check if any of them, or their dependencies, have security vulnerabilities.

### Using npm

In npm, you can use the `npm audit` command to check your dependencies. This command is available in all npm versions greater than `6.0.0`. Check [npm docs](https://docs.npmjs.com/cli/audit) for more options.

### Using yarn

Similar to npm, you can use the `yarn audit` command. It is available starting with version `1.12.0` though it is not yet available in version 2. Check the [yarn docs](https://classic.yarnpkg.com/en/docs/cli/audit/) for more options.

## Key Security

Gatsby allows you to [fetch data from various APIs](/docs/content-and-data/) and those APIs often require a key to access them. These keys should be stored in your build environment using [Environment Variables](/docs/environment-variables/). See the following example for fetching data from GitHub with an Authorization Header:

```js
{
resolve: "gatsby-source-graphql",
options: {
typeName: "GitHub",
fieldName: "github",
url: "https://api.github.com/graphql",
headers: {
// highlight-next-line
Authorization: `Bearer ${process.env.GITHUB_TOKEN}`,
},
}
}
```

### Storing keys in client-side

Sometimes in your Gatsby website, you will need display sensitive data or handle authenticated routes (e.g. a page that shows a user's orders in your ecommerce). Gatsby has an [Authentication Tutorial](/tutorial/authentication-tutorial) if you need assistance with setting up authentication flow. Use cookies to store the credentials client-side, preferably with the `SameSite` attribute listed above. Check out [MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies) to further understand these attributes and how to configure them.

## Content Security Policy (CSP)

Content Security Policy is a security layer added in web applications to detect and prevent attacks, e.g. the XSS attack mentioned above.

To add it to your Gatsby website, add [gatsby-plugin-csp](/packages/gatsby-plugin-csp/) to your `gatsby-config.js` with the desired configuration. Note that
currently there is a [compatibility issue](https://github.com/gatsbyjs/gatsby/issues/10890) between [gatsby-plugin-csp](/packages/gatsby-plugin-csp/) and other plugins that generate hashes in inline styles, including [gatsby-image](/packages/gatsby-image).

> Note that not all browsers support CSP, check [can-i-use](https://caniuse.com/#feat=mdn-http_headers_csp_content-security-policy) for more information.

## Other Resources

- [Security for Modern Web Frameworks](https://www.gatsbyjs.org/blog/2019-04-06-security-for-modern-web-frameworks/)
- [Docs ReactJS: DOM Elements](https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml)
- [OWASP XSS filter evasion cheatsheet](https://owasp.org/www-community/xss-filter-evasion-cheatsheet)
- [OWASP CSRF prevention cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#samesite-cookie-attribute)
- [Warn for javascript: URLs in DOM sinks #15047](https://github.com/facebook/react/pull/15047)
- [How to prevent XSS attacks when using dangerouslySetInnerHTML in React](https://medium.com/@Jam3/how-to-prevent-xss-attacks-when-using-dangerouslysetinnerhtml-in-react-f669f778cebb)
- [Exploiting XSS via Markdown](https://medium.com/taptuit/exploiting-xss-via-markdown-72a61e774bf8)
- [Auditing package dependencies for security vulnerabilities](https://docs.npmjs.com/auditing-package-dependencies-for-security-vulnerabilities)
- [CSRF tokens](https://portswigger.net/web-security/csrf/tokens)
- [SameSite cookies explained](https://web.dev/samesite-cookies-explained/)
2 changes: 1 addition & 1 deletion www/src/data/sidebars/doc-links.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,7 @@
link: /docs/prpl-pattern/
- title: GraphQL Concepts
link: /docs/graphql-concepts/
- title: Security in Gatsby*
- title: Security in Gatsby
link: /docs/security-in-gatsby/
- title: Theme Shadowing
link: /docs/how-shadowing-works/
Expand Down