""" Security configuration for thrillwiki project. This module configures security headers and settings to protect against common web vulnerabilities including XSS, clickjacking, MIME sniffing, and more. """ import environ env = environ.Env() # Cloudflare Turnstile settings TURNSTILE_SITE_KEY = env("TURNSTILE_SITE_KEY", default="") TURNSTILE_SECRET_KEY = env("TURNSTILE_SECRET_KEY", default="") TURNSTILE_VERIFY_URL = env( "TURNSTILE_VERIFY_URL", default="https://challenges.cloudflare.com/turnstile/v0/siteverify", ) # ============================================================================= # Security Headers Configuration # ============================================================================= # X-XSS-Protection: Enables browser's built-in XSS filter # Note: Modern browsers are deprecating this in favor of CSP, but it's still # useful for older browsers SECURE_BROWSER_XSS_FILTER = env.bool("SECURE_BROWSER_XSS_FILTER", default=True) # X-Content-Type-Options: Prevents MIME type sniffing attacks # When True, adds "X-Content-Type-Options: nosniff" header SECURE_CONTENT_TYPE_NOSNIFF = env.bool("SECURE_CONTENT_TYPE_NOSNIFF", default=True) # X-Frame-Options: Protects against clickjacking attacks # DENY = Never allow framing (most secure) # SAMEORIGIN = Only allow framing from same origin X_FRAME_OPTIONS = env("X_FRAME_OPTIONS", default="DENY") # Referrer-Policy: Controls how much referrer information is sent # strict-origin-when-cross-origin = Send full URL for same-origin, # only origin for cross-origin, nothing for downgrade SECURE_REFERRER_POLICY = env( "SECURE_REFERRER_POLICY", default="strict-origin-when-cross-origin" ) # Cross-Origin-Opener-Policy: Prevents cross-origin attacks via window references # same-origin = Document can only be accessed by windows from same origin SECURE_CROSS_ORIGIN_OPENER_POLICY = env( "SECURE_CROSS_ORIGIN_OPENER_POLICY", default="same-origin" ) # ============================================================================= # HSTS (HTTP Strict Transport Security) Configuration # ============================================================================= # Include subdomains in HSTS policy SECURE_HSTS_INCLUDE_SUBDOMAINS = env.bool( "SECURE_HSTS_INCLUDE_SUBDOMAINS", default=True ) # HSTS max-age in seconds (31536000 = 1 year, recommended minimum) SECURE_HSTS_SECONDS = env.int("SECURE_HSTS_SECONDS", default=31536000) # HSTS preload: Allow inclusion in browser preload lists # Only enable after confirming HTTPS works properly for all subdomains SECURE_HSTS_PRELOAD = env.bool("SECURE_HSTS_PRELOAD", default=False) # URLs exempt from SSL redirect (e.g., health checks) SECURE_REDIRECT_EXEMPT = env.list("SECURE_REDIRECT_EXEMPT", default=[]) # Redirect all HTTP requests to HTTPS SECURE_SSL_REDIRECT = env.bool("SECURE_SSL_REDIRECT", default=False) # Header used by proxy to indicate HTTPS (e.g., ('HTTP_X_FORWARDED_PROTO', 'https')) SECURE_PROXY_SSL_HEADER = env.tuple("SECURE_PROXY_SSL_HEADER", default=None) # ============================================================================= # Session Cookie Security # ============================================================================= # Only send session cookie over HTTPS SESSION_COOKIE_SECURE = env.bool("SESSION_COOKIE_SECURE", default=False) # Prevent JavaScript access to session cookie (mitigates XSS) SESSION_COOKIE_HTTPONLY = env.bool("SESSION_COOKIE_HTTPONLY", default=True) # SameSite attribute: Protects against CSRF attacks # Strict = Cookie only sent for same-site requests (most secure) # Lax = Cookie sent for same-site and top-level navigations (default) SESSION_COOKIE_SAMESITE = env("SESSION_COOKIE_SAMESITE", default="Lax") # ============================================================================= # CSRF Cookie Security # ============================================================================= # Only send CSRF cookie over HTTPS CSRF_COOKIE_SECURE = env.bool("CSRF_COOKIE_SECURE", default=False) # Prevent JavaScript access to CSRF cookie # Note: Set to False if you need to read the token via JavaScript for AJAX CSRF_COOKIE_HTTPONLY = env.bool("CSRF_COOKIE_HTTPONLY", default=True) # SameSite attribute for CSRF cookie CSRF_COOKIE_SAMESITE = env("CSRF_COOKIE_SAMESITE", default="Lax") # ============================================================================= # File Upload Security # ============================================================================= # Maximum size (in bytes) of file to upload into memory (2.5MB) FILE_UPLOAD_MAX_MEMORY_SIZE = env.int( "FILE_UPLOAD_MAX_MEMORY_SIZE", default=2621440 ) # Maximum size (in bytes) of request data (10MB) DATA_UPLOAD_MAX_MEMORY_SIZE = env.int( "DATA_UPLOAD_MAX_MEMORY_SIZE", default=10485760 ) # File upload permissions (0o644 = rw-r--r--) FILE_UPLOAD_PERMISSIONS = 0o644 # Directory permissions for uploaded files (0o755 = rwxr-xr-x) FILE_UPLOAD_DIRECTORY_PERMISSIONS = 0o755 # ============================================================================= # Permissions Policy (Feature Policy successor) # Controls which browser features can be used # ============================================================================= PERMISSIONS_POLICY = { "accelerometer": [], "ambient-light-sensor": [], "autoplay": [], "camera": [], "display-capture": [], "document-domain": [], "encrypted-media": [], "fullscreen": ["self"], "geolocation": ["self"], # Required for map features "gyroscope": [], "interest-cohort": [], # Block FLoC "magnetometer": [], "microphone": [], "midi": [], "payment": [], "picture-in-picture": [], "publickey-credentials-get": [], "screen-wake-lock": [], "sync-xhr": [], "usb": [], "web-share": ["self"], "xr-spatial-tracking": [], }