Skill

Configure HTTP Security Headers for Web Applications

A skill for configuring HTTP security headers - CSP, HSTS, clickjacking protection - across Nginx, Apache, Express, and Django.

Works with nginxapacheexpressdjangohelmet

Maintainer of this project? Claim this page to edit the listing.


15
Spark score
out of 100
Updated 7 months ago
Version 1.0.0

Add to Favorites

Why it matters

Implement and configure comprehensive HTTP security headers across web servers and application frameworks to protect against XSS, CSRF, clickjacking, and content injection attacks using defense-in-depth strategies.

Outcomes

What it gets done

01

Configure Content Security Policy (CSP) with progressive enhancement from report-only to strict enforcement

02

Set up HSTS, X-Frame-Options, and anti-sniffing headers in Nginx, Apache, or application middleware

03

Implement CSP violation reporting endpoints to monitor and refine security policies

04

Test and validate security header configurations across browsers using automated tools and manual inspection

Install

Add it to your toolbox

Run in your project directory:

curl -fsSL https://spark.entire.vc/get/vb-security-header-config | bash

Overview

Security Header Configuration Expert

This skill configures HTTP security headers - CSP, HSTS, X-Frame-Options, and CSP violation reporting - with working examples for Nginx, Apache, Express.js/Helmet, and Django. Use it when configuring or hardening HTTP security headers for a web application at the server, framework, or application level.

What it does

A skill acting as an expert in HTTP security headers configuration, covering defense against XSS, CSRF, clickjacking, and content injection through properly layered security headers. It documents defense-in-depth principles (layering multiple headers at both web-server and application levels, progressive enhancement starting permissive and tightening over time, testing in report-only mode before enforcement) and browser-compatibility considerations (understanding directive support, fallbacks for older browsers, mobile limitations). It provides concrete configuration for the essential headers: Content-Security-Policy (a basic policy plus a progressive report-only-then-strict rollout), X-Frame-Options versus the modern CSP frame-ancestors directive for clickjacking prevention, and Strict-Transport-Security including the preload flag. It gives working configuration examples across five layers: Nginx add_header blocks, Apache Header directives (including unsetting Server and X-Powered-By to remove server fingerprinting), Express.js via the Helmet middleware, Django settings.py (SECURE_* and CSP_* settings), and a CSP violation-report endpoint that logs blocked-uri and violated-directive fields from incoming reports. It also covers testing headers with curl and public tools (securityheaders.com, observatory.mozilla.org, hstspreload.org), a CSP rollout strategy (report-only first, monitor violations for 1-2 weeks, tighten gradually, prefer nonces over unsafe-inline/unsafe-eval), performance tips (minimize header size, strict-dynamic, unsafe-hashes over unsafe-inline), common pitfalls (conflicting X-Frame-Options vs CSP frame-ancestors, HSTS preload risk, includeSubDomains implications), and environment-specific CSP examples for development, staging, and production.

When to use - and when NOT to

Use it when configuring or hardening HTTP security headers for a web application - implementing CSP, HSTS, clickjacking protection, or setting up violation reporting - at the web-server, framework, or application level. It also covers removing server-fingerprinting headers like Server and X-Powered-By, and choosing between X-Frame-Options and the more modern CSP frame-ancestors directive for the same clickjacking-prevention goal.

Inputs and outputs

Given a web application's stack (Nginx, Apache, Express.js, or Django) and security requirements, it produces working header configuration blocks, a CSP rollout plan, and a violation-reporting endpoint implementation.

Integrations

Configuration for Nginx and Apache web servers, the Helmet middleware for Express.js, and Django's built-in SECURE_* and CSP_* settings - plus curl and third-party header-testing services (securityheaders.com, observatory.mozilla.org, hstspreload.org) for validation.

Who it's for

Web developers and security engineers hardening an application's HTTP response headers who want copy-pasteable, environment-aware configuration (development, staging, production) across common web servers and frameworks, plus a safe, monitored rollout strategy for tightening CSP without breaking legitimate resources - starting in report-only mode, watching violation reports for one to two weeks, and only then moving to full enforcement.

Source README

Security Header Configuration Expert

You are an expert in HTTP security headers configuration and implementation. You have deep knowledge of web security vulnerabilities, defense mechanisms, and how to properly configure security headers to protect web applications from attacks like XSS, CSRF, clickjacking, and content injection.

Core Security Header Principles

Defense in Depth

  • Layer multiple security headers for comprehensive protection
  • Configure headers at both web server and application levels
  • Implement progressive enhancement, starting with permissive policies and tightening over time
  • Test headers in report-only mode before enforcement

Browser Compatibility

  • Understand browser support for different header directives
  • Provide fallback mechanisms for older browsers
  • Consider mobile browser limitations
  • Test across different user agents

Essential Security Headers

Content Security Policy (CSP)

### Basic CSP implementation
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' https://apis.google.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';

### Progressive enhancement approach
### Step 1: Report-only mode
Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report-endpoint

### Step 2: Strict policy
Content-Security-Policy: default-src 'none'; script-src 'self'; style-src 'self'; img-src 'self'; connect-src 'self'; font-src 'self'; base-uri 'self'; form-action 'self';

X-Frame-Options and Frame Ancestors

### Prevent clickjacking
X-Frame-Options: DENY
### Alternative: SAMEORIGIN for same-origin framing
X-Frame-Options: SAMEORIGIN

### Modern CSP approach (preferred)
Content-Security-Policy: frame-ancestors 'none';
### Or for same-origin
Content-Security-Policy: frame-ancestors 'self';

Strict Transport Security (HSTS)

### Basic HSTS implementation
Strict-Transport-Security: max-age=31536000; includeSubDomains

### With preload (for HSTS preload list)
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

Advanced Configuration Patterns

Nginx Configuration

server {
    # Basic security headers
    add_header X-Content-Type-Options nosniff always;
    add_header X-Frame-Options DENY always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    
    # HSTS (only on HTTPS)
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
    
    # CSP
    add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' https://fonts.gstatic.com; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self';" always;
    
    # Permissions Policy
    add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
}

Apache Configuration

<VirtualHost *:443>
    # Basic security headers
    Header always set X-Content-Type-Options nosniff
    Header always set X-Frame-Options DENY
    Header always set X-XSS-Protection "1; mode=block"
    Header always set Referrer-Policy "strict-origin-when-cross-origin"
    
    # HSTS
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
    
    # CSP
    Header always set Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-ancestors 'none';"
    
    # Remove server information
    Header unset Server
    Header unset X-Powered-By
</VirtualHost>

Application-Level Implementation

Express.js with Helmet

const helmet = require('helmet');
const express = require('express');
const app = express();

app.use(helmet({
  contentSecurityPolicy: {
    directives: {
      defaultSrc: ["'self'"],
      scriptSrc: ["'self'", "'unsafe-inline'", "https://apis.google.com"],
      styleSrc: ["'self'", "'unsafe-inline'"],
      imgSrc: ["'self'", "data:", "https:"],
      fontSrc: ["'self'", "https://fonts.gstatic.com"],
      connectSrc: ["'self'"],
      frameAncestors: ["'none'"],
      baseUri: ["'self'"],
      formAction: ["'self'"]
    },
    reportOnly: false
  },
  hsts: {
    maxAge: 31536000,
    includeSubDomains: true,
    preload: true
  },
  frameguard: { action: 'deny' },
  noSniff: true,
  xssFilter: true,
  referrerPolicy: { policy: 'strict-origin-when-cross-origin' }
}));

Django Configuration

### settings.py
SECURE_CONTENT_TYPE_NOSNIFF = True
SECURE_BROWSER_XSS_FILTER = True
SECURE_HSTS_SECONDS = 31536000
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True
X_FRAME_OPTIONS = 'DENY'
SECURE_REFERRER_POLICY = 'strict-origin-when-cross-origin'

### CSP configuration
CSP_DEFAULT_SRC = ("'self'",)
CSP_SCRIPT_SRC = ("'self'",)
CSP_STYLE_SRC = ("'self'", "'unsafe-inline'")
CSP_IMG_SRC = ("'self'", "data:", "https:")
CSP_FONT_SRC = ("'self'", "https://fonts.gstatic.com")
CSP_CONNECT_SRC = ("'self'",)
CSP_FRAME_ANCESTORS = ("'none'",)
CSP_BASE_URI = ("'self'",)
CSP_FORM_ACTION = ("'self'",)

Testing and Validation

Header Testing Tools

### Test headers with curl
curl -I -s https://example.com | grep -E "(Content-Security-Policy|X-Frame-Options|Strict-Transport-Security)"

### Test CSP with browser developer tools
### Check console for CSP violations

### Online testing tools
### - securityheaders.com
### - observatory.mozilla.org
### - hstspreload.org

CSP Reporting

// CSP violation report endpoint
app.post('/csp-report', express.json({type: 'application/csp-report'}), (req, res) => {
  const report = req.body;
  console.log('CSP Violation:', JSON.stringify(report, null, 2));
  
  // Log to monitoring system
  logger.warn('CSP violation detected', {
    blockedURI: report['csp-report']['blocked-uri'],
    violatedDirective: report['csp-report']['violated-directive'],
    userAgent: req.get('User-Agent')
  });
  
  res.status(204).end();
});

Best Practices and Tips

CSP Implementation Strategy

  • Start with Content-Security-Policy-Report-Only
  • Monitor violation reports for 1-2 weeks
  • Gradually tighten policy based on legitimate resource usage
  • Use nonces for inline scripts when possible
  • Avoid unsafe-eval and unsafe-inline in production

Performance Considerations

  • Minimize header size for CSP directives
  • Use 'strict-dynamic' for modern browsers
  • Consider using 'unsafe-hashes' instead of 'unsafe-inline'
  • Cache headers appropriately

Common Pitfalls

  • Don't set conflicting headers (X-Frame-Options vs CSP frame-ancestors)
  • Test HSTS carefully before enabling preload
  • Consider subdomain implications with includeSubDomains
  • Monitor for false positives in CSP reports
  • Update headers when adding new third-party services

Environment-Specific Configuration

### Development environment
add_header Content-Security-Policy-Report-Only "default-src 'self'; report-uri /csp-report;" always;

### Staging environment
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; report-uri /csp-report;" always;

### Production environment
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self'; report-uri /csp-report;" always;

FAQ

Common questions

Discussion

Questions & comments · 0

Sign In Sign in to leave a comment.