From 9ad7128619dc3427c23d604cffa257dd2c8e7695 Mon Sep 17 00:00:00 2001 From: Steve Dogiakos Date: Sat, 28 Mar 2026 23:16:30 -0600 Subject: [PATCH] feat: add security headers, session hardening, and admin cache control Sets X-Content-Type-Options, X-Frame-Options, and Referrer-Policy on all responses. Prevents browsers from caching admin pages. Configures session cookies as HttpOnly and SameSite=Lax with an 8-hour lifetime. --- app.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/app.py b/app.py index 305c786..c868f02 100644 --- a/app.py +++ b/app.py @@ -3,7 +3,7 @@ import os import re import sqlite3 import threading -from datetime import datetime, timezone +from datetime import datetime, timedelta, timezone from zoneinfo import ZoneInfo from email_validator import validate_email, EmailNotValidError @@ -29,6 +29,21 @@ app.secret_key = _secret_key limiter = Limiter(get_remote_address, app=app, default_limits=[]) +app.config.update( + SESSION_COOKIE_HTTPONLY=True, + SESSION_COOKIE_SAMESITE='Lax', + PERMANENT_SESSION_LIFETIME=timedelta(hours=8), +) + +@app.after_request +def set_security_headers(response): + response.headers['X-Content-Type-Options'] = 'nosniff' + response.headers['X-Frame-Options'] = 'SAMEORIGIN' + response.headers['Referrer-Policy'] = 'strict-origin-when-cross-origin' + if request.path.startswith('/admin'): + response.headers['Cache-Control'] = 'no-store' + return response + _DISPLAY_TZ = ZoneInfo('America/Denver') @app.template_filter('localtime')