<commit_before>---
title: Security for Modern Web Frameworks.
date: 2019-04-06
author: <NAME>
excerpt: "While more secure than their server-side counterparts, modern web frameworks provide new and unique security concerns."
tags:
  - security
  - api
  - JAMstack
---

Among the many lauded benefits of using Gatsby (and other static app frameworks) is security. It is encouraging to see a framework not require developers to stress about security, but for those new to Gatsby or web development, this can contribute to a myth that there are no security issues.

There are indeed whole classes of security vulnerabilities that are eliminated by using Gatsby for web development; but there are still other vulnerabilities that are shared and some that are created. As a Gatsby developer, you need to make sure you are aware of these possible vulnerabilities and how to remedy them.

This post will act as an introduction to get you familiar with these concepts in Gatsby.

## Defining Terms

These are not to be considered universal definitions, just how the author will use them going forward.

- **site** - Any website, web-app, or other content you can browse on the internet in a web browser.

- **server-side site** - Any site that pre-processes code at time of request -- whether using node.js, PHP, Python, or any other method -- before delivering it to the user's browser.

- **client-side site** - Any site (GatsbyJS, NuxtJS, NextJS, Single Page App, etc...) where static files(HTML/CSS/JS) are shipped to the browser for processing -- pre-processing may happen at build time, but does not happen time of request.

- **attack vector** - A resource through which to hack a site. Just because an attack vector exists does not mean your site is vulnerable to that attack, however. A server is an attack vector; but, the server requires a vulnerability for an attacker to exploit (use) that server as an attack vector.

## Shared Security Concerns

No matter how you deploy your site, how little JavaScript you use, whether it is sever-side or client-side: your site has attack vectors.

When it comes to client-side sites, if you are going to get hacked, it is likely going to be at the infrastructure or network level:

- **Infrastructure** - This might be your CDN, code repository, DNS, CI, etc. Thanks to the cloud, most of the work securing this layer is done for you. As long as, you are using two-factor authentication (2FA) and a strong password. You are all using 2FA (when possible) and strong passwords, right!? Good.

- **Network** - This kind of attack happens when an attacker can access to the network being used to access your site. It could be a rouge third-party in your cloud provider, or someone sitting across the coffee shop on the same public WiFi as your user. The exact attack methods vary, but are collectively referred to as a [Man-in-the-Middle](https://en.wikipedia.org/wiki/Man-in-the-middle_attack) attack.
  The defense here is HTTPS (TLS encryption). Other related technologies such as [Cross-Origin-Resource-Sharing](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS), [Strict-Transport-Security](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security), [Public Key Pinning](*https://developer.mozilla.org/en-US/docs/Web/HTTP/Public_Key_Pinning), and [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) all assist in securing network traffic. No matter who is looking at your network traffic, they can not read or modify it.

Other possible attacks relate to using `iframes` without securing them or not removing referrer tags on external links. Thankfully, fixing these is a pretty low bar. More on this later.

## Unique Security Concerns

When you ship **everything** to the browser, the user can access **everything**. No amount of minification or obfuscation can hide the code and content you are shipping. If a user knows how to use their browser's dev tools, the user can get that content. This makes showing dynamic or private content on client-side sites seemingly impossible. This is why server-side rendering of sites was invented.

In the server-side world the solution is to...well there is not really a problem to begin with because all the secrets and private content is secured on a server. The client browser never needs to directly access them. The server fetches content from the API or database, and sends back only the content the client is authorized to access.

How do you secure secrets in the client-side world, if all the content and code is being shipped to the client browser? An answer can be found with the "[JAMstack](https://jamstack.org/)". Hopefully you are all fairly familiar with this concept given you are building "JAMstack" sites using Gatsby. For the uninitiated: you use HTML/CSS ([M]arkup) to build your site, [J]avaScript to make it dynamic, and [A]PIs to provide content and features. All of this is done from the client-side.

The biggest security struggle with client-side sites is securing those APIs. Most APIs require an API key or another kind of authentication. Simply adding those secrets to the code only further obfuscates access to the same content. It does nothing to actually secure that content.

What's the solution? Well there are several problems to solve.

**Quick Definitions**:

- **Private** - unique to a person or group of people using your site.
- **Public** - accessible to any and all users on your site.
- **Dynamic** - any content that is updated more than once in a 5 minute interval and needs to be accessible to all users of the site.
- **Static** - any content that changes less than once in a given 5 minute interval.

NOTE: 5 minutes is somewhat arbitrary. 5 minutes is used because anything changed **less often** generally just means rebuilding and deploying your site with an automated CI/CD pipeline. Build times make anything changed **more often** tricky. This build time problem is a core tenant of [Gatsby](https://www.gatsbyjs.com/) and future features (like [incremental builds](https://github.com/gatsbyjs/gatsby/issues/5002)) that will speed up build times significantly.

So, you could have private-static content, private-dynamic content, public-static content, and public-dynamic content. You also need to be aware of whether you are securing the ability to read or write content. Without further delay, in order of difficulty...

### Public Static Content

This is by far the most common and simplest content to secure. This makes up the content of your marketing site, public blog, etc. In a Gatsby site, this content can be added statically via HTML or dynamically at build time via a [source plugin](/docs/source-plugin-tutorial/). Whatever source platform you use, whether it be a GitHub repository or a headless CMS, that platform is charged with securing your content from unauthorized reads and writes.

If you are using a headless CMS, the static content is fetched at build time and Gatsby will need an API key to do so. For example, [gatsby-source-contentful](/packages/gatsby-source-contentful/?=contentful) requires an `accessToken`. While this is a 'read-only' token, exposing it to the public in your code would mean anyone could take your structured data and use it any way they want.

Fortunately, this is an easy fix using [environment variables](https://www.gatsbyjs.org/docs/environment-variables/). This means not committing your `accessToken` to the git repository for all the world to read. Instead it is stored securely on the build server and your Contentful config reads like this:

```js:title=gatsby-config.js
{
  resolve: `gatsby-source-contentful`,
  options: {
    spaceId: `your_space_id`,
    // Learn about environment variables: https://gatsby.dev/env-vars
    accessToken: process.env.CONTENTFUL_ACCESS_TOKEN,
  },
},<commit_msg>Clarify in blog post that accessTokens in code aren't available to everyone (#13200)<commit_after>---
title: Security for Modern Web Frameworks.
date: 2019-04-06
author: <NAME>
excerpt: "While more secure than their server-side counterparts, modern web frameworks provide new and unique security concerns."
tags:
  - security
  - api
  - JAMstack
---

Among the many lauded benefits of using Gatsby (and other static app frameworks) is security. It is encouraging to see a framework not require developers to stress about security, but for those new to Gatsby or web development, this can contribute to a myth that there are no security issues.

There are indeed whole classes of security vulnerabilities that are eliminated by using Gatsby for web development; but there are still other vulnerabilities that are shared and some that are created. As a Gatsby developer, you need to make sure you are aware of these possible vulnerabilities and how to remedy them.

This post will act as an introduction to get you familiar with these concepts in Gatsby.

## Defining Terms

These are not to be considered universal definitions, just how the author will use them going forward.

- **site** - Any website, web-app, or other content you can browse on the internet in a web browser.

- **server-side site** - Any site that pre-processes code at time of request -- whether using node.js, PHP, Python, or any other method -- before delivering it to the user's browser.

- **client-side site** - Any site (GatsbyJS, NuxtJS, NextJS, Single Page App, etc...) where static files(HTML/CSS/JS) are shipped to the browser for processing -- pre-processing may happen at build time, but does not happen time of request.

- **attack vector** - A resource through which to hack a site. Just because an attack vector exists does not mean your site is vulnerable to that attack, however. A server is an attack vector; but, the server requires a vulnerability for an attacker to exploit (use) that server as an attack vector.

## Shared Security Concerns

No matter how you deploy your site, how little JavaScript you use, whether it is sever-side or client-side: your site has attack vectors.

When it comes to client-side sites, if you are going to get hacked, it is likely going to be at the infrastructure or network level:

- **Infrastructure** - This might be your CDN, code repository, DNS, CI, etc. Thanks to the cloud, most of the work securing this layer is done for you. As long as, you are using two-factor authentication (2FA) and a strong password. You are all using 2FA (when possible) and strong passwords, right!? Good.

- **Network** - This kind of attack happens when an attacker can access to the network being used to access your site. It could be a rouge third-party in your cloud provider, or someone sitting across the coffee shop on the same public WiFi as your user. The exact attack methods vary, but are collectively referred to as a [Man-in-the-Middle](https://en.wikipedia.org/wiki/Man-in-the-middle_attack) attack.
  The defense here is HTTPS (TLS encryption). Other related technologies such as [Cross-Origin-Resource-Sharing](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS), [Strict-Transport-Security](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security), [Public Key Pinning](*https://developer.mozilla.org/en-US/docs/Web/HTTP/Public_Key_Pinning), and [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) all assist in securing network traffic. No matter who is looking at your network traffic, they can not read or modify it.

Other possible attacks relate to using `iframes` without securing them or not removing referrer tags on external links. Thankfully, fixing these is a pretty low bar. More on this later.

## Unique Security Concerns

When you ship **everything** to the browser, the user can access **everything**. No amount of minification or obfuscation can hide the code and content you are shipping. If a user knows how to use their browser's dev tools, the user can get that content. This makes showing dynamic or private content on client-side sites seemingly impossible. This is why server-side rendering of sites was invented.

In the server-side world the solution is to...well there is not really a problem to begin with because all the secrets and private content is secured on a server. The client browser never needs to directly access them. The server fetches content from the API or database, and sends back only the content the client is authorized to access.

How do you secure secrets in the client-side world, if all the content and code is being shipped to the client browser? An answer can be found with the "[JAMstack](https://jamstack.org/)". Hopefully you are all fairly familiar with this concept given you are building "JAMstack" sites using Gatsby. For the uninitiated: you use HTML/CSS ([M]arkup) to build your site, [J]avaScript to make it dynamic, and [A]PIs to provide content and features. All of this is done from the client-side.

The biggest security struggle with client-side sites is securing those APIs. Most APIs require an API key or another kind of authentication. Simply adding those secrets to the code only further obfuscates access to the same content. It does nothing to actually secure that content.

What's the solution? Well there are several problems to solve.

**Quick Definitions**:

- **Private** - unique to a person or group of people using your site.
- **Public** - accessible to any and all users on your site.
- **Dynamic** - any content that is updated more than once in a 5 minute interval and needs to be accessible to all users of the site.
- **Static** - any content that changes less than once in a given 5 minute interval.

NOTE: 5 minutes is somewhat arbitrary. 5 minutes is used because anything changed **less often** generally just means rebuilding and deploying your site with an automated CI/CD pipeline. Build times make anything changed **more often** tricky. This build time problem is a core tenant of [Gatsby](https://www.gatsbyjs.com/) and future features (like [incremental builds](https://github.com/gatsbyjs/gatsby/issues/5002)) that will speed up build times significantly.

So, you could have private-static content, private-dynamic content, public-static content, and public-dynamic content. You also need to be aware of whether you are securing the ability to read or write content. Without further delay, in order of difficulty...

### Public Static Content

This is by far the most common and simplest content to secure. This makes up the content of your marketing site, public blog, etc. In a Gatsby site, this content can be added statically via HTML or dynamically at build time via a [source plugin](/docs/source-plugin-tutorial/). Whatever source platform you use, whether it be a GitHub repository or a headless CMS, that platform is charged with securing your content from unauthorized reads and writes.

If you are using a headless CMS, the static content is fetched at build time and Gatsby will need an API key to do so. For example, [gatsby-source-contentful](/packages/gatsby-source-contentful/?=contentful) requires an `accessToken`. While this is a 'read-only' token, exposing it in your code would mean anyone with access to your code repository could take your structured data and use it any way they want.

Fortunately, this is an easy fix using [environment variables](https://www.gatsbyjs.org/docs/environment-variables/). This means not committing your `accessToken` to the git repository where many can possibly access it. Instead it is stored securely on the build server and your Contentful config reads like this:

```js:title=gatsby-config.js
{
  resolve: `gatsby-source-contentful`,
  options: {
    spaceId: `your_space_id`,
    // Learn about environment variables: https://gatsby.dev/env-vars
    accessToken: process.env.CONTENTFUL_ACCESS_TOKEN,
  },
},
{'fraction_non_alphanumeric': 0.06509511470644, 'fraction_numerical': 0.002591164760159262, 'mean_word_length': 4.320780094149294, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 20, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4229638', 'n_tokens_mistral': 4014, 'n_tokens_neox': 3842, 'n_words': 2299}