Security Headers

Easy

Detects missing headers (CSP, HSTS, X-Frame-Options).

Estimated fix time: 10 minutes

What are Security Headers?

HTTP security headers are directives that tell browsers how to behave when handling your site's content. They provide crucial protection against various attacks including XSS, clickjacking, and MIME sniffing.

Security Impact

Severity: High

  • Cross-Site Scripting (XSS) attacks
  • Clickjacking vulnerabilities
  • MIME sniffing attacks
  • Man-in-the-middle attacks

Required Security Headers

1. Content Security Policy (CSP)

Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline';

2. HTTP Strict Transport Security (HSTS)

Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

3. X-Frame-Options

X-Frame-Options: SAMEORIGIN

4. X-Content-Type-Options

X-Content-Type-Options: nosniff

5. Referrer Policy

Referrer-Policy: strict-origin-when-cross-origin

6. Permissions Policy

Permissions-Policy: geolocation=(), microphone=(), camera=()

How to Fix

Method 1: Using Middleware

Create a custom middleware:

php artisan make:middleware SecurityHeaders
// app/Http/Middleware/SecurityHeaders.php
namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class SecurityHeaders
{
    public function handle(Request $request, Closure $next)
    {
        $response = $next($request);

        $response->headers->set('X-Frame-Options', 'SAMEORIGIN');
        $response->headers->set('X-Content-Type-Options', 'nosniff');
        $response->headers->set('X-XSS-Protection', '1; mode=block');
        $response->headers->set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
        $response->headers->set('Referrer-Policy', 'strict-origin-when-cross-origin');
        $response->headers->set('Permissions-Policy', 'geolocation=(), microphone=(), camera=()');
        
        // CSP Header
        $response->headers->set('Content-Security-Policy', 
            "default-src 'self'; " .
            "script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.jsdelivr.net; " .
            "style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; " .
            "font-src 'self' https://fonts.gstatic.com; " .
            "img-src 'self' data: https:; " .
            "connect-src 'self';"
        );

        return $response;
    }
}

Register the middleware:

// app/Http/Kernel.php
protected $middlewareGroups = [
    'web' => [
        // ... other middleware
        \App\Http\Middleware\SecurityHeaders::class,
    ],
];

Method 2: Using .htaccess (Apache)

# .htaccess
<IfModule mod_headers.c>
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set X-Content-Type-Options "nosniff"
    Header always set X-XSS-Protection "1; mode=block"
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
    Header always set Referrer-Policy "strict-origin-when-cross-origin"
    Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()"
    Header always set Content-Security-Policy "default-src 'self'"
</IfModule>

Method 3: Using Nginx

# nginx configuration
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
add_header Content-Security-Policy "default-src 'self'" always;

Verification Steps

  1. Open your website in Chrome DevTools
  2. Go to Network tab
  3. Click on your page request
  4. Check the Response Headers section
  5. Verify all security headers are present

Or use online tools:

CSP Configuration Tips

Start with a restrictive policy and gradually relax it:

// Development CSP
"default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval';"

// Production CSP (more restrictive)
"default-src 'self'; script-src 'self'; style-src 'self';"

Report CSP violations:

"report-uri /csp-report-endpoint;"

Common Pitfalls

  • Don't use 'unsafe-inline' and 'unsafe-eval' in production CSP if possible
  • Test HSTS carefully before setting long max-age values
  • Ensure CSP allows all legitimate resources (CDNs, fonts, etc.)
  • SSL/TLS Security
  • CORS Misconfiguration
  • Laravel Debug Mode

Automatically detect this issue

StackShield can automatically scan your Laravel application for this security issue and alert you when it's detected.

Start Free Trial
Was this guide helpful?