fix: TLS verification, cookie hardening, and proxy transport (#7)

- Renamed _ssl_ctx to _internal_ssl_ctx (explicitly scoped to internal services)
- Image proxy now uses default SSL context (TLS verification enabled for external URLs)
- Logout cookie clearing now includes HttpOnly, Secure, SameSite=Lax
- proxy.py still uses internal context (Docker services have no valid certs)

Closes #7
This commit is contained in:
Yusuf Suleman
2026-03-29 09:13:37 -05:00
parent 590ea69900
commit 5f5660893d
3 changed files with 11 additions and 7 deletions

View File

@@ -58,7 +58,7 @@ def handle_logout(handler):
delete_session(token)
handler.send_response(200)
handler.send_header("Content-Type", "application/json")
handler.send_header("Set-Cookie", "platform_session=; Path=/; Max-Age=0")
handler.send_header("Set-Cookie", "platform_session=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0")
resp = b'{"success": true}'
handler.send_header("Content-Length", len(resp))
handler.end_headers()

View File

@@ -62,7 +62,11 @@ SESSION_MAX_AGE = int(os.environ.get("SESSION_MAX_AGE", 30 * 86400)) # 30 days
# ── Ensure data dir exists ──
DATA_DIR.mkdir(parents=True, exist_ok=True)
# ── Shared SSL context (skip verification for internal services) ──
_ssl_ctx = ssl.create_default_context()
_ssl_ctx.check_hostname = False
_ssl_ctx.verify_mode = ssl.CERT_NONE
# ── SSL contexts ──
# Internal: skip verification for Docker-internal services (no valid certs)
_internal_ssl_ctx = ssl.create_default_context()
_internal_ssl_ctx.check_hostname = False
_internal_ssl_ctx.verify_mode = ssl.CERT_NONE
# Legacy alias — to be removed once all callers are updated
_ssl_ctx = _internal_ssl_ctx

View File

@@ -5,7 +5,7 @@ Platform Gateway — Image proxy with domain allowlist.
import urllib.request
import urllib.parse
from config import _ssl_ctx
# No custom SSL context — external URLs use default TLS verification
ALLOWED_IMAGE_DOMAINS = {
"i.redd.it",
@@ -59,7 +59,7 @@ def handle_image_proxy(handler):
"Accept": "image/*,*/*",
"Referer": parsed.scheme + "://" + parsed.netloc + "/",
})
resp = urllib.request.urlopen(req, timeout=10, context=_ssl_ctx)
resp = urllib.request.urlopen(req, timeout=10)
body = resp.read()
ct = resp.headers.get("Content-Type", "image/jpeg")
# Only serve actual image content types