← Back to Blog
Security Web 16 min read

Web Security Headers: Complete Implementation Guide

Learn web security headers implementation, Content Security Policy (CSP), HTTP security headers, and best practices for securing web applications.

Why Security Headers Matter

HTTP security headers provide an additional layer of protection for web applications. They help prevent common attacks like cross-site scripting (XSS), clickjacking, MIME type sniffing, and other security vulnerabilities. Properly configured security headers are essential for modern web application security.

Security Headers Benefits: Security headers are a defense-in-depth measure that works alongside other security controls. They're implemented at the server level and provide protection without requiring changes to application code.

Essential Security Headers

Content Security Policy (CSP)

Prevents XSS attacks by controlling resource loading:

Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.cdn.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; connect-src 'self' https://api.example.com; frame-ancestors 'none'; base-uri 'self'; form-action 'self';

Protects against: XSS, data injection, mixed content

Strict-Transport-Security (HSTS)

Forces HTTPS connections:

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

Protects against: SSL stripping, man-in-the-middle

X-Content-Type-Options

Prevents MIME type sniffing:

X-Content-Type-Options: nosniff

Protects against: MIME confusion attacks

X-Frame-Options

Prevents clickjacking:

X-Frame-Options: DENY # or X-Frame-Options: SAMEORIGIN

Protects against: Clickjacking, UI redressing

Content Security Policy (CSP) Implementation

1. CSP Directives Explained

Understanding common CSP directives:

# Basic CSP Policy Content-Security-Policy: default-src 'self'; # Default: same origin only script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.jsdelivr.net; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' data: https:; # Allow data URLs and all HTTPS images font-src 'self' https://fonts.gstatic.com; connect-src 'self' https://api.example.com; # XHR, fetch, WebSocket frame-src 'none'; # No embedded frames object-src 'none'; # No Flash, Java, etc. media-src 'self'; # Audio/video from same origin manifest-src 'self'; # Web app manifest worker-src 'self'; # Service workers, shared workers base-uri 'self'; # Restrict element form-action 'self'; # Restrict form submissions frame-ancestors 'none'; # Prevent embedding (replaces X-Frame-Options) report-uri /csp-violation-report; # Report violations

2. CSP Nonce and Hash

Allow inline scripts/styles securely:

# Server generates unique nonce for each request Content-Security-Policy: script-src 'nonce-2726c7f26c' 'strict-dynamic'; style-src 'nonce-2726c7f26c'; # In HTML # Using hash instead of nonce Content-Security-Policy: script-src 'sha256-abc123...'; # Script with matching hash

3. CSP Reporting

Monitor CSP violations during implementation:

# Report-Only mode (doesn't block, only reports) Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self'; report-uri /csp-report; report-to csp-endpoint; # Production mode (blocks violations) Content-Security-Policy: default-src 'self'; script-src 'self'; report-uri /csp-report; # Report endpoint example (Node.js/Express) app.post('/csp-report', (req, res) => { const report = req.body; console.log('CSP Violation:', report); // Log to monitoring service res.status(204).end(); });

Additional Security Headers

Referrer-Policy

Controls referrer information:

Referrer-Policy: no-referrer-when-downgrade # Other options: # no-referrer # origin # origin-when-cross-origin # same-origin # strict-origin # strict-origin-when-cross-origin # unsafe-url

Protects privacy, prevents information leakage

Permissions-Policy

Controls browser features:

Permissions-Policy: camera=(), microphone=(), geolocation=(self "https://maps.example.com"), payment=(self), usb=()

Controls access to browser APIs and sensors

Feature-Policy (Legacy)

Predecessor to Permissions-Policy:

Feature-Policy: camera 'none'; microphone 'none'; geolocation 'self'; payment 'self'; sync-xhr 'none'

Being replaced by Permissions-Policy

X-XSS-Protection

Legacy XSS protection:

X-XSS-Protection: 0 # Disable (use CSP instead) # or X-XSS-Protection: 1; mode=block

Deprecated, use CSP for XSS protection

Implementation Examples

1. Nginx Configuration

Security headers in Nginx:

# /etc/nginx/conf.d/security-headers.conf add_header 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; img-src 'self' data: https:; font-src 'self' https://fonts.gstatic.com; connect-src 'self' https://api.example.com; frame-src 'none'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none';"; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; add_header X-Content-Type-Options "nosniff" always; add_header X-Frame-Options "DENY" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; add_header Permissions-Policy "camera=(), microphone=(), geolocation=(self), payment=(self), usb=()" always; add_header X-XSS-Protection "0"; # Disable legacy protection # For static files location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ { add_header Cache-Control "public, max-age=31536000"; }

2. Apache Configuration

Security headers in Apache:

# .htaccess or httpd.conf Header 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; img-src 'self' data: https:; font-src 'self' https://fonts.gstatic.com; connect-src 'self' https://api.example.com; frame-src 'none'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none';" Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" Header always set X-Content-Type-Options "nosniff" Header always set X-Frame-Options "DENY" Header always set Referrer-Policy "strict-origin-when-cross-origin" Header always set Permissions-Policy "camera=(), microphone=(), geolocation=(self), payment=(self), usb=()" Header set X-XSS-Protection "0" # For static files Header set Cache-Control "public, max-age=31536000"

3. Node.js/Express Implementation

Security headers in Express middleware:

const helmet = require('helmet'); const express = require('express'); const app = express(); // Use helmet with custom configuration app.use(helmet({ contentSecurityPolicy: { directives: { defaultSrc: ["'self'"], scriptSrc: ["'self'", "'unsafe-inline'", "'unsafe-eval'", "https://cdn.jsdelivr.net"], styleSrc: ["'self'", "'unsafe-inline'", "https://fonts.googleapis.com"], imgSrc: ["'self'", "data:", "https:"], fontSrc: ["'self'", "https://fonts.gstatic.com"], connectSrc: ["'self'", "https://api.example.com"], frameSrc: ["'none'"], objectSrc: ["'none'"], baseUri: ["'self'"], formAction: ["'self'"], frameAncestors: ["'none'"], }, }, hsts: { maxAge: 31536000, includeSubDomains: true, preload: true }, referrerPolicy: { policy: 'strict-origin-when-cross-origin' }, permissionsPolicy: { features: { camera: ["'none'"], microphone: ["'none'"], geolocation: ["'self'"], payment: ["'self'"], usb: ["'none'"] } } })); // Custom headers app.use((req, res, next) => { res.setHeader('X-Content-Type-Options', 'nosniff'); res.setHeader('X-Frame-Options', 'DENY'); res.setHeader('X-XSS-Protection', '0'); // Disable legacy next(); });

Testing and Validation

Testing Tools

  • SecurityHeaders.com - Comprehensive header analysis
  • Mozilla Observatory - Security scanning tool
  • Google Lighthouse - Performance and security audit
  • curl/HTTPie - Manual header inspection
  • Browser DevTools - Network panel inspection

Monitoring Tools

  • CSP Report-Only - Monitor violations before enforcement
  • Security monitoring services - Continuous monitoring
  • Log analysis - Track CSP violation reports
  • Automated scanning - Regular security scans

Conclusion and Best Practices

Security Headers Implementation Checklist

  • ✓ Implement CSP with report-only mode first
  • ✓ Enable HSTS with preload directive
  • ✓ Set X-Content-Type-Options: nosniff
  • ✓ Configure X-Frame-Options or frame-ancestors
  • ✓ Set appropriate Referrer-Policy
  • ✓ Configure Permissions-Policy for browser features
  • ✓ Test headers with security scanning tools
  • ✓ Monitor CSP violation reports regularly

Security headers are a critical component of web application security. They provide defense-in-depth protection against common attacks and should be implemented as part of a comprehensive security strategy. Start with the essential headers, test thoroughly, and monitor for issues. Remember that security is an ongoing process, not a one-time configuration.

Related Tools on DailyTools.uk

Check out our developer tools that can help with security: