Files
ObsiGate/backend/services/net.py
T
bruno 162a5b4acc
CI / lint (push) Successful in 1m20s
CI / security (push) Successful in 47s
CI / test (push) Successful in 2m21s
CI / build (push) Successful in 43s
CI / e2e (push) Successful in 10m48s
fix(security): consolidation & securite phase 1 (#84, BUG-021 a BUG-034)
- sanitizer XSS serveur (markdown + page de partage) [BUG-021/022]
- rate-limit/lockout MFA [BUG-023]
- isolation vaults par segments [BUG-024]
- caps regex ReDoS [BUG-025]
- SSRF webhooks + secrets externalises [BUG-026]
- rotation/revocation des jetons [BUG-027]
- politique de mot de passe + invalidation sessions [BUG-028]
- verrous users.json [BUG-029]
- IP reelle dans les audits [BUG-030]
- rate-limit par compte [BUG-031]
- symlinks hors vault ignores [BUG-032]
- recherche simple via inverted index [BUG-033]
- token en memoire + cookie HttpOnly, CSP durcie [BUG-034]

Tests: pytest 961 passed / 6 skipped, ruff 0, mypy 0, frontend vert.
2026-09-13 10:51:42 -04:00

35 lines
1.1 KiB
Python

"""Network helpers shared by the auth middleware and rate limiter."""
from __future__ import annotations
import os
from fastapi import Request
__all__ = ["get_client_ip", "is_trusted_proxy"]
def is_trusted_proxy() -> bool:
"""Whether ``X-Forwarded-For`` should be trusted (reverse proxy in front)."""
return os.environ.get("OBSIGATE_TRUST_PROXY", "false").lower() == "true"
def get_client_ip(request: Request) -> str:
"""Return the best-known client IP for *request*.
When ``OBSIGATE_TRUST_PROXY=true`` the left-most ``X-Forwarded-For`` entry
is used (the original client behind the proxy). Otherwise the socket peer
address is returned. BUG-030: this value feeds the audit log so attacks
remain traceable.
"""
if is_trusted_proxy():
forwarded = request.headers.get("x-forwarded-for")
if forwarded:
first = forwarded.split(",")[0].strip()
if first:
return first
real_ip = request.headers.get("x-real-ip")
if real_ip:
return real_ip.strip()
return request.client.host if request.client else "unknown"