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 20 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
144 changes: 140 additions & 4 deletions docs/docs/security-in-gatsby.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,145 @@
---
title: Security in Gatsby
issue: https://github.com/gatsbyjs/gatsby/issues/13305
---

This is a stub. Help our community expand it.
By being a modern static site generator, Gatsby inherits several security principles that comes with this approach. However, even with this, your users could be exposed to malicious attacks. In this page, you will see what they are and how you could prevent them.
luizcieslak marked this conversation as resolved.
Show resolved Hide resolved

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 a unexpected link to another site into the client side of the application.
luizcieslak marked this conversation as resolved.
Show resolved Hide resolved

JSX elements automatically escapes HTML tags by design. So, when you try to inject them as the example below:
luizcieslak marked this conversation as resolved.
Show resolved Hide resolved

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

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

it will render `hello <script src='https://path/to/badness.js'></script>` as a string inside the p tag.
luizcieslak marked this conversation as resolved.
Show resolved Hide resolved

In other hand, there could be some fields in your application that you will need to render the inner HTML tags, such as a content field in a blog or a comment in a comments section, that are built in rich-text editors.
luizcieslak marked this conversation as resolved.
Show resolved Hide resolved

That's when you expose your application to XSS attacks, since the way to render these HTML tags is by using a HTML parser (e.g. [html-react-parser](https://github.com/remarkablemark/html-react-parser)) or using the `dangerouslySetInnerHTML` prop, as this example below:
luizcieslak marked this conversation as resolved.
Show resolved Hide resolved

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

luizcieslak marked this conversation as resolved.
Show resolved Hide resolved
**How can it be prevented?**
luizcieslak marked this conversation as resolved.
Show resolved Hide resolved

The most straightforward way to prevent the XSS attack is to sanitize the innerHTML string before dangerously setting it. Fortunately, there are npm packages that does the job, like [sanitize-html](https://www.npmjs.com/package/sanitize-html) and [DOMPurify](https://github.com/cure53/DOMPurify).
luizcieslak marked this conversation as resolved.
Show resolved Hide resolved

## Cross-Site Request Forgery (CSRF)

A web application that use cookies could be attacked by the CSRF exploit, which deceives the browser to execute actions by the user's name without notice. By default, the browser "trusts" all the activity made validating the user's identity and therefore sending the associated cookies in every request.
Copy link
Contributor

Choose a reason for hiding this comment

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

This needs to be re written it's pretty confusing. https://en.wikipedia.org/wiki/Cross-site_request_forgery has some good explanations you can quote from. If you do choose to fix what you have I think it would still be helpful to link out to a more complete resource like Wikipedia for those interested in diving deeper than the quick overviews we're providing here (this applies to XSS as well).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In these past few days, I'm exploring more in the topic in CS253 - Web Security classes from Stanford. I'll rewrite this section, making it simple, doing some quotes and linking these resources.


For example, assume that the comments done in your blog are sent in a form like this below:
luizcieslak marked this conversation as resolved.
Show resolved Hide resolved

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

A malicious website could inspect your site and copy it to theirs. If the user are logged in, it still works because when the form is sent, the associated cookies goes with it and the action is made. Even worse, the form could be sent when the page loads with informations you don't control:
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
A malicious website could inspect your site and copy it to theirs. If the user are logged in, it still works because when the form is sent, the associated cookies goes with it and the action is made. Even worse, the form could be sent when the page loads with informations you don't control:
A malicious website could inspect your site and copy it to theirs. If the user is logged in, it still works because when the form is sent, the associated cookies goes with it and the action is made. Even worse, the form could be sent when the page loads with information you don't control:

Not sure I understand the middle sentence. Is the goal to explain that this is true for unauthenticated AND authenticated users?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sorry, it's confusing. It only works if you are authenticated to the original website. I'm going to rewrite this section.


```js
// highlight-next-line
<body onload="document.csrf.submit()">
<!-- ... -->
<form action="http://mywebsite.com/blog/addcoment" 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 it be prevented?**
Copy link
Contributor

Choose a reason for hiding this comment

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

You "copy the site" example above could be fixed by simply scoping your cookies to a certain domain. Make sure you info is accurate (I'm no expert here either) and complete (aka. solve every problem you present, and do so correctly). Again, I think since security is such a deep and nuanced topic it'll be to your benefit to keep these short and simple then link out to more complete resources.

Copy link
Contributor

Choose a reason for hiding this comment

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

on further thought...Based on how this info is presented Tokens seem to be "THE" solution. I'm guessing they are just one, of many solutions. Present it as such, "On way CSRF attacks can be mitigated..., .... To read more on this topic check out....", then link out to more in depth resources.

Copy link
Contributor

Choose a reason for hiding this comment

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

Sry I just realized you do have the Same-site cookies example...Fix you headings please The "How Can it be prevented" should probably be a ### header and then each example be #### header. Optionally, Instead of presenting several problems then several solutions, Give one problem, and its solution, then another and its solution...etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, sorry about that! I think that is good we are learning things while doing this. I'm gonna rewrite this section.

Copy link
Contributor

Choose a reason for hiding this comment

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

no need to be sorry. you're doing great work, just trying to give helpful feedback. thanks and keep it up. I've already learned a thing or two.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You are!

luizcieslak marked this conversation as resolved.
Show resolved Hide resolved

### CSRF Tokens
luizcieslak marked this conversation as resolved.
Show resolved Hide resolved

In a page you want to protect, your server will provide an encrypted, hard to guess **token**, which is tied to the user's session and thus will be required to be sent back in the POST form:
luizcieslak marked this conversation as resolved.
Show resolved Hide resolved

```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>
```

So when the form is sent, the server will compare them and block the action if they are not the same. Note that usually the malicious website won't have access to this CSRF token because of [HTTP Access Control](https://developer.mozilla.org/pt-BR/docs/Web/HTTP/Headers/Access-Control-Allow-Origin).
luizcieslak marked this conversation as resolved.
Show resolved Hide resolved

### Same-Site Cookies Directive
luizcieslak marked this conversation as resolved.
Show resolved Hide resolved

If you need to create cookies in your application, make sure to protect them by adding the `SameSite` directive:

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?

`Set-Cookie: example=1; SameSite=Strict`
laurieontech marked this conversation as resolved.
Show resolved Hide resolved

It allows the server to make sure that the cookies are not being sent by a **cross-site** domain request.
luizcieslak marked this conversation as resolved.
Show resolved Hide resolved
Check out [MDN Docs](https://developer.mozilla.org/pt-BR/docs/Web/HTTP/Headers/Set-Cookie) regarding how a cookie could be configured. [Most moderns browsers support it with a backward compatibility](https://caniuse.com/#feat=same-site-cookie-attribute).
luizcieslak marked this conversation as resolved.
Show resolved Hide resolved

## Third-party Scripts

Some third-party scripts like Google Tag Manager gives the possibility to add arbitrary JavaScript code on top of them as a [custom HTML tag](https://support.google.com/tagmanager/answer/6107167), which can be a malicious script. To avoid that, be sure to have a [access control](https://support.google.com/tagmanager/answer/6107011) management in these services.
luizcieslak marked this conversation as resolved.
Show resolved Hide resolved

## Check Your Dependencies

In your Gatsby project, you are going to have a lot of dependencies (which has their own dependencies as well) in your `node_modules/`. Therefore, it is important to check if any of them has a security issue.
luizcieslak marked this conversation as resolved.
Show resolved Hide resolved

**Using `npm`**
luizcieslak marked this conversation as resolved.
Show resolved Hide resolved

In npm, you can use the `npm audit` command to check your dependencies. It is available since v6. Check their [docs](https://docs.npmjs.com/cli/audit) for more options.
luizcieslak marked this conversation as resolved.
Show resolved Hide resolved

**Using `yarn`**
luizcieslak marked this conversation as resolved.
Show resolved Hide resolved

Similar to `npm`, you can use the `yarn audit` command. It is available since v1.12.0, not available in v2. Check their [docs](https://classic.yarnpkg.com/en/docs/cli/audit/) for more options.
luizcieslak marked this conversation as resolved.
Show resolved Hide resolved

## Key Security

Gatsby provides the capability of [fetching data from anywhere](/docs/content-and-data/) and by that you should know that most of this data requires a key to access them. These keys should be stored in the server by using [Environment Variables](/docs/environment-variables/) as this example below, fetching data from GitHub with an Authentication Header:
luizcieslak marked this conversation as resolved.
Show resolved Hide resolved

```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}`,
},
}
}
```

Note: Whether you need to authenticate someone in your application, Gatsby has an [Authentication Tutorial](/tutorial/authentication-tutorial) which helps doing this job in a secure way.
Copy link
Contributor

Choose a reason for hiding this comment

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

This covers build variables well but not client side keys. Not sure if the note is intended to cover it cause the language is a bit confusing.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, this note does not cover this part. What do you think it should be here regarding client-side keys? encryption? known methods, e.g. JWT?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think this doc should be a starting point. so defining the issue and maybe an example of how to solve then (again) links out to more thorough resources (like Gatsby's docs on keys and env variables).

luizcieslak marked this conversation as resolved.
Show resolved Hide resolved

## 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 [incompatibility issue](https://github.com/gatsbyjs/gatsby/issues/10890) between [gatsby-plugin-csp](/packages/gatsby-plugin-csp/) and [gatsby-image](/packages/gatsby-image) and other plugins that generate hashes in inline styles.
luizcieslak marked this conversation as resolved.
Show resolved Hide resolved

Note: Not all browsers support CSP, check [can-i-use](https://caniuse.com/#feat=mdn-http_headers_csp_content-security-policy) for more information.
luizcieslak marked this conversation as resolved.
Show resolved Hide resolved

## 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)
- [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 @@ -603,7 +603,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