CloudFront Security Headers Configuration

Implement security headers through CloudFront response headers policies for enhanced browser-level protection.

Security headers protect users from XSS, clickjacking, and other browser-based attacks. CloudFront's response headers policies allow centralized header management across all origins.

Creating Response Headers Policies

Using AWS CLI

aws cloudfront create-response-headers-policy \
  --response-headers-policy-config '{
    "Name": "SecurityHeadersPolicy",
    "Comment": "Production security headers",
    "SecurityHeadersConfig": {
      "XSSProtection": {
        "Override": true,
        "Protection": true,
        "ModeBlock": true
      },
      "FrameOptions": {
        "Override": true,
        "FrameOption": "DENY"
      },
      "ContentTypeOptions": {
        "Override": true
      },
      "StrictTransportSecurity": {
        "Override": true,
        "AccessControlMaxAgeSec": 31536000,
        "IncludeSubdomains": true,
        "Preload": true
      },
      "ContentSecurityPolicy": {
        "Override": true,
        "ContentSecurityPolicy": "default-src '"'"'self'"'"'; script-src '"'"'self'"'"' '"'"'unsafe-inline'"'"'; style-src '"'"'self'"'"' '"'"'unsafe-inline'"'"';"
      },
      "ReferrerPolicy": {
        "Override": true,
        "ReferrerPolicy": "strict-origin-when-cross-origin"
      }
    }
  }'

CloudFormation Template

ResponseHeadersPolicy:
  Type: AWS::CloudFront::ResponseHeadersPolicy
  Properties:
    ResponseHeadersPolicyConfig:
      Name: ProductionSecurityHeaders
      SecurityHeadersConfig:
        ContentSecurityPolicy:
          ContentSecurityPolicy: "default-src 'self'; img-src 'self' data: https:; script-src 'self'; style-src 'self' 'unsafe-inline'; font-src 'self' data:; connect-src 'self' https://api.example.com"
          Override: true
        StrictTransportSecurity:
          AccessControlMaxAgeSec: 31536000
          IncludeSubdomains: true
          Preload: true
          Override: true
        FrameOptions:
          FrameOption: DENY
          Override: true
        ContentTypeOptions:
          Override: true
        XSSProtection:
          Protection: true
          ModeBlock: true
          Override: true
        ReferrerPolicy:
          ReferrerPolicy: strict-origin-when-cross-origin
          Override: true
      CustomHeadersConfig:
        Items:
          - Header: Permissions-Policy
            Value: "geolocation=(), microphone=(), camera=()"
            Override: true

Content Security Policy Design

Developing CSP Incrementally

Start with report-only mode:

// Report-only CSP for testing
const reportOnlyCSP = {
  "Content-Security-Policy-Report-Only": 
    "default-src 'self'; " +
    "script-src 'self' 'report-sample'; " +
    "report-uri /csp-violation-report"
};

Processing CSP Violation Reports

import json
from flask import Flask, request

app = Flask(__name__)

@app.route('/csp-violation-report', methods=['POST'])
def csp_report():
    report = json.loads(request.data)
    violation = report.get('csp-report', {})
    
    log_violation({
        'blocked_uri': violation.get('blocked-uri'),
        'document_uri': violation.get('document-uri'),
        'violated_directive': violation.get('violated-directive'),
        'original_policy': violation.get('original-policy'),
        'source_file': violation.get('source-file'),
        'line_number': violation.get('line-number')
    })
    
    return '', 204

HSTS Implementation

Preload List Submission

Requirements for HSTS preload:

  1. Valid HTTPS certificate
  2. max-age >= 31536000 (1 year)
  3. includeSubDomains directive
  4. preload directive
  5. Redirect HTTP to HTTPS
# Verify HSTS configuration
curl -I https://example.com | grep -i strict-transport

# Expected output:
# strict-transport-security: max-age=31536000; includeSubDomains; preload

Permissions Policy

Control browser feature access:

CustomHeadersConfig:
  Items:
    - Header: Permissions-Policy
      Value: >-
        accelerometer=(),
        ambient-light-sensor=(),
        autoplay=(),
        battery=(),
        camera=(),
        display-capture=(),
        document-domain=(),
        encrypted-media=(),
        geolocation=(),
        gyroscope=(),
        magnetometer=(),
        microphone=(),
        midi=(),
        payment=(),
        picture-in-picture=(self),
        usb=(),
        xr-spatial-tracking=()
      Override: true

Testing Security Headers

# Comprehensive header check
curl -I https://example.com | grep -iE "(content-security|strict-transport|x-frame|x-content|x-xss|referrer|permissions)"

# Using securityheaders.com API
curl "https://securityheaders.com/?q=example.com&followRedirects=on"

Working with Warqline

We are a cloud engineering consultancy and an official AWS and Google Cloud partner. If you are running this in production and want a second pair of eyes, we scope work in a free 45-minute technical call: you describe what you are running and what worries you, and we tell you what we would look at first.

Talk to an engineer

Conclusion

Security headers are essential for protecting users from client-side attacks. CloudFront response headers policies enable consistent, centralized header management across your entire application.