Using Layer0’s EdgeJS to Configure Custom Security Headers
Tags: layer0, security, beginners, serverless
Published: 2022-03-18 18:22:49

Implementing Security Headers has become extremely important way to reduce the number of website breaches and data thefts that take place every day. This post breaks down the nine most important Security Headers.

Implementing Security Headers has become extremely important as the number of breaches and data thefts are increasing rapidly every day. Security Headers offer an easy to implement part of the solution: Simply pass specific HTTP Headers to protect your website from common attacks like XSS, code injection, clickjacking, etc.

# What are Security Headers?

Web applications can send special commands to the browser to protect websites from breaches or client-side vulnerabilities, known as Security Headers.

When a user visits a website in their browser, the server responds with HTTP Response Headers. These headers, composed of metadata, share information with the client and server. This shared information defines how the browsers should interact with the website. Security headers provide powerful protection from a wide variety of web app vulnerabilities and threats.

This blog will break down the following important security headers:

- Content Security Policy (CSP)
- X-Content-Type-Options
- X-Frame-Options
- Cross-Origin Resource Policy (CORP)
- Cross-Origin Embedder Policy (COEP)
- Cross-Origin Opener Policy (COOP)
- Referrer-Policy
- Permissions-Policy
- HTTP Strict Transport Security (HSTS)

# Importance of Security Headers
HTTP security headers are a fundamental part of website security, however only [1.6% of the top one million websites](https://ieeexplore.ieee.org/document/8405025) have implemented Content Security Policy (CSP) and only a mere .2% of sites implement CSP-Report-Only.

Shocking, right?! The lack of CSP HTTP Header takes down the defense mechanisms against Cross-Site Scripting (XSS) and other client-side injection attacks. [British Airways data breach](https://en.wikipedia.org/wiki/British_Airways_data_breach) is one of the incidents which illustrates how due to a lack of client side security, the names, street addresses, email addresses, credit card numbers, expiration dates and Card security codes of 380,000 customers were exposed which remained undetected for 15 days.

# Adding Security with Layer0’s EdgeJS

With Layer0’s deployment platform, things like [TLS are automatically configured](https://docs.layer0.co/guides/production#section_tls_ssl) for each deploy link, so that developers can ship securely by default. In this blog, we take a close look at important security headers and an example to show how quick you can secure a website with [routes config on Layer0](https://docs.layer0.co/guides/security?sgId=f65413b7-c7e3-438b-bce2-dd2ed1de90e5#section_security).

![Getting Started with Security Headers with Layer0](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pz279yz4z2r82g5ed0rp.png)

# Content Security Policy (CSP)

![How CSP Prevents Loading Resources From Not-Allowed Origins](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qv3ellx1py4t4zcx2z48.png)

Content-Security-Policy provides an added layer to prevent [Cross-Site Scripting (XSS)](https://www.google.com/about/appsecurity/learning/xss/) attacks by restricting scripts, styles, images, fonts and media to be loaded (and executed) from specific allowed origins. Regardless of how secure your backend is, if bad actors are able to attack the code that runs in the browser instead of on the server, user session data is compromised and confidential information is exposed. One of the many examples (such as the British Airways Data Breach) is the MageCart attack on Ticketmaster’s payment module. [The Ticketmaster breach](https://www.riskiq.com/blog/external-threat-management/magecart-ticketmaster-breach/) resulted in 40,000 victims of credit card theft and it remained active for 5 months before being caught! All just by injecting a [form skimming script](https://www.riskiq.com/blog/external-threat-management/magecart-ticketmaster-breach/#:~:text=At%20the%20very%20end%20of%20these%20scripts%2C%20the%20Magecart%20skimmer%20can%20be%20seen%3A) inside the browser.

```js
const { Router } = require('@layer0/core/router')

const ContentSecurityPolicy = `
  default-src 'self';
  script-src 'self' 'unsafe-eval' 'unsafe-inline' *.layer0.co;
  style-src 'self' 'unsafe-inline' *.googleapis.com;
  img-src * blob: data:;
  media-src 'none';
  connect-src *;
  font-src 'self' *.gstatic.com;
`;

new Router()
  .get("/:route", ({ setResponseHeader }) => {
    setResponseHeader("Content-Security-Policy", ContentSecurityPolicy.replace(/\n/g, ""))
  })
``` 

Content-Security-Policy gives you the ability to: 

- Overcome XSS (Cross Site Scripting) attacks
- Prevent Clickjacking
- [Report violation(s) to the CSP rules](https://www.mstsolutions.com/technical/preventing-xss-with-%E2%80%8Bcontent-security-policy/#:~:text=require%C2%A0manual%20modifications.-,Reporting%20violation,-Whenever%20the%20defined)

# X-Content-Type-Options

![How Configuring X-Content-Type-Options prevents MIME-Type Sniffing](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x9cl4fmu6fzt4d47w3hu.png)

The X-Content-Type-Options Header is used to indicate that MIME (Multipurpose Internet Mail Extensions, an identifier for file formats) Types specified in the Content-Type headers shall be strictly followed. With [MIME Type Sniffing](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types#mime_sniffing), operations such as image upload can be used to run executables which could be malicious and that’s where the X-Content-Type-Options header comes into play.

```js
const { Router } = require('@layer0/core/router')

new Router()
  .get("/:route", ({ setResponseHeader }) => {
    setResponseHeader("X-Content-Type-Options", "nosniff")
  })
```

# X-Frame-Options

![X-Frame-Options Header](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xgbd8zrl77dfaye04034.png)

The X-Frame-Options header is used to indicate whether a browser should be allowed to render a page in a frame, iframe, embed or object tag(s) to avoid [click-jacking](https://developer.mozilla.org/en-US/docs/Web/Security/Types_of_attacks#click-jacking) attacks. Whether set to DENY or SAMEORIGIN ensures that their content is not embedded into other sites or only embedded into sites with the same origin respectively.
‍ 
```js
const { Router } = require('@layer0/core/router')

new Router()
  .get("/:route", ({ setResponseHeader }) => {
    setResponseHeader("X-Frame-Options", "SAMEORIGIN")
  })
```

X-Frame-Options gives you the ability to: 

- Prevent Clickjacking attacks
- Indicate whether or not a browser should be allowed to render a page in a <frame>, <iframe>, <embed> or <object>

# Cross-Origin Resource Policy (CORP)

CORP allows servers to protect against certain cross-origin or cross-site embedding of the requested resource (for e.g. API responses). **It also prevents speculative side-channel attacks like [Spectre](https://en.wikipedia.org/wiki/Spectre_(security_vulnerability)).**

```js
const { Router } = require('@layer0/core/router')

new Router()
  .get("/:route", ({ setResponseHeader }) => {
    setResponseHeader("Cross-Origin-Resource-Policy", "same-origin")
  })
```

Cross-Origin Resource Policy is an opt-in response header which can protect any resource; there is no need for browsers to sniff MIME types. — [MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cross-Origin_Resource_Policy_(CORP)#history)

# Cross-Origin Embedder Policy (COEP)

COEP header prevents loading of cross-origin resources that have not been granted permission for (via CORS or CORP). Use ‘require-corp’ to enforce the header, while ‘unsafe-none’ to allow fetching cross-origin documents.

```js
const { Router } = require('@layer0/core/router')

new Router()
  .get("/:route", ({ setResponseHeader }) => {
    setResponseHeader("Cross-Origin-Embedder-Policy", "require-corp")
  })
```

# Cross-Origin Opener Policy (COOP)

Enforcing COOP header ensures that a top-level document’s browsing context group is not shared between cross-origin documents. While ‘same-origin’ breaks the integrations that require cross-origin window interactions such as OAuth and Payment, ‘same-origin-allow-popups’ aims to share the context with only the popups from the SAMEORIGIN.

```js
const { Router } = require('@layer0/core/router')

new Router()
  .get("/:route", ({ setResponseHeader }) => {
    setResponseHeader("Cross-Origin-Opener-Policy", "same-origin-allow-popups")
  })
```

# Referrer Policy

When a user navigates (clicking on a link) from one site (the origin) to another (the destination), the latter receives information about the origin the user came from. The Referrer-Policy header controls how much of this information shall be available to the destination. For all the directives of Referrer-Policy, refer to [Referrer-Policy — HTTP | MDN (mozilla.org)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy#directives).

```js
const { Router } = require("@layer0/core/router")

module.exports= new Router()
  .get("/", ({ setResponseHeader }) => {
    setResponseHeader("Referrer-Policy", "origin-when-cross-origin")
  })
```

# Permissions Policy

An experimental HTTP Header that provides the ability to allow/deny browser features in its own frames, and in any iframe in the document. For all the directives of Referrer-Policy, refer to [Feature-Policy — HTTP | MDN (mozilla.org)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Feature-Policy)

```js
const { Router } = require("@layer0/core/router")

module.exports= new Router()
  .get("/", ({ setResponseHeader }) => {    
    setResponseHeader(
      "Permissions-Policy", "camera=(), microphone=(), geolocation=()"
    );
  })
```

# HTTP Strict Transport Security (HSTS)

![HSTS Strict Transport Security Header](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c7z5g45ea2bgoavr6sl9.png)
 
HTTP Strict-Transport-Security (HSTS) informs the browsers to load the web site only using HTTPS, instead of using the HTTP Protocol.

```js
const { Router } = require('@layer0/core/router')

new Router()
  .get("/:route", ({ setResponseHeader }) => {
    setResponseHeader("Strict-Transport-Security", "max-age=31536000; includeSubDomains")
  })
```

HSTS gives you the ability to:

- Protect against [HTTP downgrade attacks](https://www.keyfactor.com/blog/what-are-ssl-stripping-attacks/) (SSL stripping attacks)
- Mixed content defense, switches to HTTPS by default


# An Example

With Layer0, it’s easier than ever to implement Security Headers. By using Layer0’s EdgeJS, you are able to add security headers to any website, independent of the framework being used. The following seeks to implement the relevant security headers in a website built with Sapper via Layer0.

- Example: [https://rishi-raj-jain-security-headers-example-default.layer0-limelight.link](https://rishi-raj-jain-security-headers-example-default.layer0-limelight.link)
- GitHub: [rishi-raj-jain/security-headers-example](https://github.com/rishi-raj-jain/security-headers-example)
- Report: [Security Headers Report Link](https://securityheaders.com/?q=https%3A%2F%2Frishi-raj-jain-security-headers-example-default.layer0-limelight.link)

![Security Headers Report Summary](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dejqiddpbhbpq134r7fi.png)

# Discussion 

Go ahead and add relevant security headers to secure your web application! With Layer0 you can do even more than this, secrets, cache poisoning and enabling basic authentication at [Layer0 Documentation — Security](https://docs.layer0.co/guides/security).