security: set SESSION_COOKIE_SECURE + validate IP before nginx deny write
Two hardening fixes from a fresh security pass of the live code: - SESSION_COOKIE_SECURE=True: the session cookie set only HTTPONLY + SAMESITE=Lax, so it could be sent over plaintext HTTP. App is served behind nginx TLS, so no functional downside. - _nginx_ban: validate the IP with ipaddress.ip_address() before interpolating it into the nginx deny file. A malformed value could otherwise inject nginx directives at the last write before reload. Guard sits at the sink, covering all current and future callers. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
083f05c093
commit
ea0ba33212
@ -35,6 +35,7 @@ if not _flask_secret:
|
|||||||
app.secret_key = _flask_secret
|
app.secret_key = _flask_secret
|
||||||
app.config["SESSION_COOKIE_HTTPONLY"] = True
|
app.config["SESSION_COOKIE_HTTPONLY"] = True
|
||||||
app.config["SESSION_COOKIE_SAMESITE"] = "Lax"
|
app.config["SESSION_COOKIE_SAMESITE"] = "Lax"
|
||||||
|
app.config["SESSION_COOKIE_SECURE"] = True # served behind nginx TLS; prevents cookie leak over plaintext HTTP
|
||||||
|
|
||||||
# ─── SECURITY LOGGING ─────────────────────────────────────────
|
# ─── SECURITY LOGGING ─────────────────────────────────────────
|
||||||
# Dedicated security log for fail2ban and audit trail.
|
# Dedicated security log for fail2ban and audit trail.
|
||||||
@ -7687,6 +7688,16 @@ def _nginx_ban(ip):
|
|||||||
if is_allowlisted(ip):
|
if is_allowlisted(ip):
|
||||||
sec_log.info("NGINX_BAN_BLOCKED ip=%s — allowlisted, refused to write deny rule", ip)
|
sec_log.info("NGINX_BAN_BLOCKED ip=%s — allowlisted, refused to write deny rule", ip)
|
||||||
return
|
return
|
||||||
|
# Defense in depth: validate IP format before interpolating into the
|
||||||
|
# nginx conf. A malformed value (e.g. "1.2.3.4;\n}\nserver{...") would
|
||||||
|
# otherwise inject directives into the deny file. Last write before
|
||||||
|
# reload — last place to stop a bad ban (matches docstring intent).
|
||||||
|
import ipaddress
|
||||||
|
try:
|
||||||
|
ipaddress.ip_address(ip)
|
||||||
|
except ValueError:
|
||||||
|
sec_log.warning("NGINX_BAN_INVALID_IP ip=%r — refused to write deny rule (possible nginx config injection)", ip)
|
||||||
|
return
|
||||||
import subprocess
|
import subprocess
|
||||||
line = f"deny {ip};\n"
|
line = f"deny {ip};\n"
|
||||||
# Each step has its own try/except so we know WHICH step failed.
|
# Each step has its own try/except so we know WHICH step failed.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user