security: fix #1 — wire SSRF hook into cache download client
Adds validate_public_request to the cache module's shared httpx client event_hooks. Covers image/video/thumbnail downloads, which are the most likely exfil path — file_url comes straight from the booru JSON response and previously followed any 3xx that landed, so a hostile booru could point downloads at a private IP. Every redirect hop is now rejected if the target is non-public. The import is lazy inside _get_shared_client because core.api.base imports log_connection from this module; a top-level `from .api._safety import ...` would circular-import through api/__init__.py during cache.py load. By the time _get_shared_client is called the api package is fully loaded. Audit-Ref: SECURITY_AUDIT.md finding #1 Severity: High
This commit is contained in:
parent
6eebb77ae5
commit
ec79be9c83
@ -79,6 +79,10 @@ def _get_shared_client(referer: str = "") -> httpx.AsyncClient:
|
||||
c = _shared_client
|
||||
if c is not None and not c.is_closed:
|
||||
return c
|
||||
# Lazy import: core.api.base imports log_connection from this
|
||||
# module, so a top-level `from .api._safety import ...` would
|
||||
# circular-import through api/__init__.py during cache.py load.
|
||||
from .api._safety import validate_public_request
|
||||
with _shared_client_lock:
|
||||
c = _shared_client
|
||||
if c is None or c.is_closed:
|
||||
@ -89,6 +93,7 @@ def _get_shared_client(referer: str = "") -> httpx.AsyncClient:
|
||||
},
|
||||
follow_redirects=True,
|
||||
timeout=60.0,
|
||||
event_hooks={"request": [validate_public_request]},
|
||||
limits=httpx.Limits(max_connections=10, max_keepalive_connections=5),
|
||||
)
|
||||
_shared_client = c
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user