Files
winauthmon-server/utils/security_headers.py
T
2025-05-25 20:26:18 +01:00

67 lines
2.5 KiB
Python

import os
import logging
from flask import request, current_app
logger = logging.getLogger(__name__)
def add_security_headers(response):
"""
Add security headers to HTTP responses
Headers added:
- Content-Security-Policy: Prevents XSS attacks by specifying content sources
- X-Content-Type-Options: Prevents MIME type sniffing
- X-Frame-Options: Prevents clickjacking
- X-XSS-Protection: Additional XSS protection for older browsers
- Referrer-Policy: Controls referrer information
- Strict-Transport-Security: Enforces HTTPS
- Permissions-Policy: Controls browser features
"""
# Content Security Policy - restricts sources of content
csp = current_app.config.get('CONTENT_SECURITY_POLICY',
"default-src 'self'; "
"script-src 'self' 'unsafe-inline'; "
"style-src 'self' 'unsafe-inline'; "
"img-src 'self' data:; "
"font-src 'self'; "
"connect-src 'self'; "
"frame-ancestors 'self'; "
"form-action 'self'; "
"base-uri 'self'"
)
response.headers['Content-Security-Policy'] = csp
# Prevent MIME type sniffing
response.headers['X-Content-Type-Options'] = 'nosniff'
# Prevent clickjacking
response.headers['X-Frame-Options'] = 'SAMEORIGIN'
# Additional XSS protection for older browsers
response.headers['X-XSS-Protection'] = '1; mode=block'
# Control referrer information
response.headers['Referrer-Policy'] = 'strict-origin-when-cross-origin'
# HSTS - force HTTPS (only in production)
if not current_app.debug and not current_app.testing:
hsts_enabled = current_app.config.get('HSTS_ENABLED', True)
if hsts_enabled:
hsts_max_age = current_app.config.get('HSTS_MAX_AGE', 31536000)
response.headers['Strict-Transport-Security'] = f'max-age={hsts_max_age}; includeSubDomains'
# Permissions Policy (formerly Feature-Policy)
response.headers['Permissions-Policy'] = (
'camera=(), microphone=(), geolocation=(), interest-cohort=()'
)
return response
def setup_security_headers(app, config=None):
"""Register security headers middleware with Flask app"""
if config and config.getboolean('security', 'ENABLE_SECURITY_HEADERS', fallback=True):
# Set CSP from config if available
if config.has_option('security', 'CONTENT_SECURITY_POLICY'):
app.config['CONTENT_SECURITY_POLICY'] = config.get('security', 'CONTENT_SECURITY_POLICY')
app.after_request(add_security_headers)