R13: Fix X-Forwarded-For trust boundary — only trust from known proxies

- Add _is_trusted_proxy() to check client IP against trusted CIDRs
- Only use X-Forwarded-For if connection came from trusted proxy
- Add TRUSTED_PROXY_CIDRS config (default: 127.0.0.1/32, ::1/128)
- Add parse_comma_separated_lists for env var parsing
- Add 3 unit tests: trusted CIDR check, untrusted ignores forwarded, trusted uses forwarded
This commit is contained in:
ik
2026-09-10 05:49:23 +07:00
parent cc3b42eaf6
commit e2bed0db89
4 changed files with 100 additions and 15 deletions
+12
View File
@@ -33,6 +33,18 @@ class Settings(BaseSettings):
rate_limit_secret: str = "change-rate-limit-secret"
log_level: str = "INFO"
cors_origins: list[str] = Field(default_factory=lambda: ["http://localhost:4321", "http://127.0.0.1:4321"])
trusted_proxy_cidrs: list[str] = Field(default_factory=lambda: ["127.0.0.1/32", "::1/128"])
@model_validator(mode="before")
@classmethod
def parse_comma_separated_lists(cls, data: dict) -> dict:
"""Parse comma-separated string values into lists."""
if isinstance(data, dict):
for field_name in ["cors_origins", "trusted_proxy_cidrs"]:
value = data.get(field_name)
if isinstance(value, str) and value:
data[field_name] = [item.strip() for item in value.split(",") if item.strip()]
return data
model_config = SettingsConfigDict(env_file=".env", extra="ignore")
@model_validator(mode="after")