> ## Content Index
> Fetch the complete content index at: https://securinglaravel.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Security Tip: Security Headers are Layers of Defence
- URL: https://securinglaravel.com/security-tip-security-headers-are/
- Published: 2023-05-25T20:00:47.000Z
- Updated: 2025-04-15T04:17:49.000Z
- Description: [Tip#46] Security headers add important layers of defence to your apps, preventing data leaks, XSS and CSRF attacks, clickjacking, and more... Why are you leaving your apps unprotected?
- Author: Stephen Rees-Carter
- Tags: Security Tips, Audits Top 10, CSRF, Headers

ℹ️

**This is part of my series on the* [**Top 10 Security Issues*](https://securinglaravel.com/tag/audits-top-10/) *discovered during my Laravel Security Audits, as of April 2023\.*   
  
**#1 →* [**Exposed API Keys & Passwords*](https://securinglaravel.com/in-depth-storing-environment-variables/)  
**#2 →* [**Missing Authorisation*](https://securinglaravel.com/security-tip-test-for-missing-authorisation/)  
**#3 →* [**Missing Content Security Policy (CSP)*](https://securinglaravel.com/security-tip-getting-started-with-csp/)  
***#4 → Missing Security Headers**  
**#5 →* [**Insecure Function Use*](https://securinglaravel.com/in-depth-what-are-insecure-functions/)  
**#6 →* [**Outdated & Vulnerable Dependencies*](https://securinglaravel.com/security-tip-replace-simple-dependencies/)  
**#7 →* [**Cross-Site Scripting (XSS)*](https://securinglaravel.com/security-tip-avoiding-xss-with-htmlstring/)  
**#8 →* [**Insufficient Rate Limiting*](https://securinglaravel.com/security-tip-dont-forget-rate-limiting/)  
**#9 →* [**Missing Subresource Integrity (SRI)*](https://securinglaravel.com/security-tip-subresource-integrity/)  
**#10 →* [**Insufficient Input Validation*](https://securinglaravel.com/security-tip-validating-array-inputs/) *&* [**Mass-Assignment Vulnerabilities*](https://securinglaravel.com/in-depth-mass-assignment-vulnerabilities/)

There is a common concept in the security industry known as *Defence in Depth* or *Security in Depth*, which can be summed up simply as having multiple defences layered on top of each other, so if one fails, the next one keeps you protected. This is the key idea behind security headers within browsers - they protect your app if your other defences fail, sometimes due to factors outside your control.

The best place to get started with security headers is with the excellent [Security Headers scanner](https://securityheaders.com/?ref=securinglaravel.com) project by [Scott Helme](https://scotthelme.co.uk/?ref=securinglaravel.com). The way it works is really simple, you give it your site address and it makes a request and checks what headers are included in the response. It then gives you a score and tells you which headers you’re missing.

If we take a look at my personal website, [stephenreescarter.net](https://stephenreescarter.net/?ref=securinglaravel.com), we can see it scores a A+! 🤓

![](https://storage.ghost.io/c/d9/0d/d90de76f-6031-4e2c-85b8-3447a38c4992/content/images/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https-3a-2f-2fsubstack-post-media.s3.amazonaws.com-2fpublic-2fimages-2f62e1ea1a-5ff5-4cd5-abf5-7d6060746189_947x253.png)

“A+” result for stephenreescarter.net

~~Since~~ [~~securinglaravel.com~~](https://securinglaravel.com/) ~~is powered by Substack, it’s limited to what headers they include and only gets a D… 😭~~

![](https://storage.ghost.io/c/d9/0d/d90de76f-6031-4e2c-85b8-3447a38c4992/content/images/2024/07/https-3a-2f-2fsubstack-post-media.s3.amazonaws.com-2fpublic-2fimages-2f7075c66e-f6b5-4e3a-a20c-7342f0dab514_942x253.png)

“D” result for securinglaravel.com

Now on Ghost, it scores a pitiful F... 😱 *I need to figure out how to add some headers!*

![](https://storage.ghost.io/c/d9/0d/d90de76f-6031-4e2c-85b8-3447a38c4992/content/images/2024/07/image-1.png)

And since I know some of you will be wondering, [laravel.com](https://laravel.com/?ref=securinglaravel.com) scores a D too! 

*So if anyone the Laravel team are reading this… you’ve got work to do!* 😜

![](https://storage.ghost.io/c/d9/0d/d90de76f-6031-4e2c-85b8-3447a38c4992/content/images/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https-3a-2f-2fsubstack-post-media.s3.amazonaws.com-2fpublic-2fimages-2f3051c4e2-6e28-47e4-8e0e-3933817b62c1_945x257.png)

“D” result for laravel.com

So now you know which headers you’re missing, let’s quickly run through what each header does, and point you in the right direction to get it enabled.

## `Content-Security-Policy`

[I’ve covered Content Security Policies before](https://securinglaravel.com/tag/csp/), so I recommend checking out that post. We’ll also touch on them next week, since *(spoiler alert!) “Missing Content Security*” Policies is #3 on the top 10!

## `Referrer-Policy`

Controls what referrer information is sent when the user navigates from your site to a different site. The current browser default value is `strict-origin-when-cross-origin`, which is a fairly sane default for many apps.

You should consider changing this value if your app shouldn’t broadcast it’s domain, i.e. for internal tooling, or private or sensitive apps. You can also tweak it if you want to broadcast complete referrers.

Referrer information can leak sensitive paths or even query string parameters, so you need to be aware of what the setting is and what information it is sharing.

[Find out more...](https://securinglaravel.com/security-tip-is-your-referrer-leaking-information/)

```
Referrer-Policy: no-referrer
Referrer-Policy: no-referrer-when-downgrade
Referrer-Policy: origin
Referrer-Policy: origin-when-cross-origin
Referrer-Policy: same-origin
Referrer-Policy: strict-origin
Referrer-Policy: strict-origin-when-cross-origin
Referrer-Policy: unsafe-url
```

## `Permissions-Policy`

This is a newer header that defines what browser features the app has permissions to use. The idea being that you can disable things like the webcam and microphone in the header, so if an attacker compromises your site and injects some javascript, it can’t turn on the victim’s camera and mic and record them. In this way it’s similar to a CSP - preventing future exploitation of an existing vulnerability.

The easiest way to get started is to use the generator over at [permissionspolicy.com](https://www.permissionspolicy.com/?ref=securinglaravel.com).

```
Permissions-Policy: <directive> <allowlist>
```

[Find out more...](https://securinglaravel.com/security-tip-do-you-have-a-permissions-policy/)

## `Strict-Transport-Security` (HSTS)

Informs the browser to always use HTTPS when connecting to that domain in the future (up until the expiry date). This prevents Person In The Middle Downgrade attacks that revert the connection back to unencrypted HTTP.

If you domain doesn’t require HTTP, then there isn’t much reason to not enable this on your domain. You can optionally enable it across all subdomains to cover your entire app, and add it to the [preload list](https://hstspreload.org/?ref=securinglaravel.com) to avoid the Trust On First Use (TOFU) problem.

💡

****TOFU → Trust On First Use.**  
The first request must be trusted, as it contains the HSTS header instructing the browser to require HTTPS. If the first request is intercepted, the HSTS header can be stripped and bypassed, removing it’s protection. The preload list avoids this by shipping the list of HSTS domains with the browser, so it will never make a HTTP request to a domain on the list. 

Some newer extensions, such as `.dev` and `.app` are included on the preload list already, giving you HSTS out of the box.

```
Strict-Transport-Security: max-age=<expire-time>
Strict-Transport-Security: max-age=<expire-time>; includeSubDomains
Strict-Transport-Security: max-age=<expire-time>; includeSubDomains; preload
```

[Find out more...](https://securinglaravel.com/security-tip-how-strict-is-your-transport-security/)

## `X-Content-Type-Options`

Prevents the browser from trying to guess the content type of response/file from it’s MIME type and instead trust the `Content-Type` header. This is important to prevent uploaded files from tricking the browser into doing things it isn’t supposed to do, such as downloading or executing files.

There is a single value, which you can safely enable in almost all use cases:

```
X-Content-Type-Options: nosniff
```

[More information on the mdm web docs…](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options?ref=securinglaravel.com)

## `X-Frame-Options`

Prevents your site from being embedded within a frame, either by blocking all frames or only allowing a site to embed itself. This directly prevent clickjacking attacks.

Unless you specifically need to allow frames from third parties, you can safely enable the header with one of these options:

```
X-Frame-Options: DENY       << block all frames
X-Frame-Options: SAMEORIGIN << allow site to embed itself
```

Note, it is no longer possible to allow other sites to embed yours through this header. This has been moved to the [Content Security Policy](https://securinglaravel.com/in-depth-content-security-policy/) header with its `frame-ancestors` directive.

[More information on the mdm web docs…](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options?ref=securinglaravel.com)

## Dishonourable Mention: `X-XSS-Protection`

This was a non-standard header implemented on some browsers to try and protect against simple XSS attacks. It never really worked well, and in specific cases it actually caused XSS vulnerabilities. [It has since been removed](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection?ref=securinglaravel.com), so there is no reason to implement it.

---

***If you found this security tip useful,*** [***subscribe***](#/portal/signup) ***to get weekly*** [***Security Tips***](https://securinglaravel.com/tag/tips/) **straight to your inbox.* Upgrade to a* [*premium subscription*](#/portal/signup) *for exclusive monthly* [*In Depth articles*](https://securinglaravel.com/tag/in-depth/)*, or drop a coin in the* [*tip jar*](#/portal/support) *to show your support.*

*When was the last time you had a penetration test? Book a* [*Laravel Security Audit and Penetration Test*](https://stephenreescarter.net/laravel-security-audits-and-pentesting/?utm%5Fsource=securinglaravel.com)*, or a budget-friendly* [*Security Review*](https://stephenreescarter.net/laravel-security-reviews/?utm%5Fsource=securinglaravel.com)*!* 

*You can also connect with me on* [*Bluesky*](https://bsky.app/profile/valorin.bsky.social?ref=securinglaravel.com)*, or* [*other socials*](https://pinkary.com/@valorin?ref=securinglaravel.com)*, and check out* [*Practical Laravel Security*](https://practicallaravelsecurity.com/?utm%5Fsource=securinglaravel.com)*, my interactive course designed to boost your Laravel security skills.*