From ef955095513c2426c355dfad3217e5154708a0d9 Mon Sep 17 00:00:00 2001 From: pax Date: Sat, 11 Apr 2026 16:11:12 -0500 Subject: [PATCH] =?UTF-8?q?security:=20fix=20#1=20=E2=80=94=20wire=20SSRF?= =?UTF-8?q?=20hook=20into=20E621Client=20custom=20client?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit E621 maintains its own httpx.AsyncClient because their TOS requires a per-user User-Agent string that BooruClient's shared client can't carry. The client is rebuilt on User-Agent change, so the hook must be installed in the same construction path. Also installs BooruClient._log_request as a second hook (this additionally closes finding #16 for the e621 client — e621 requests previously bypassed the connection log entirely, and this wires them in consistently with the base client). Audit-Ref: SECURITY_AUDIT.md finding #1 Also-Closes: SECURITY_AUDIT.md finding #16 (e621 half) Severity: High --- booru_viewer/core/api/e621.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/booru_viewer/core/api/e621.py b/booru_viewer/core/api/e621.py index 66d1da5..1171355 100644 --- a/booru_viewer/core/api/e621.py +++ b/booru_viewer/core/api/e621.py @@ -8,6 +8,7 @@ import threading import httpx from ..config import DEFAULT_PAGE_SIZE, USER_AGENT +from ._safety import validate_public_request from .base import BooruClient, Post, _parse_date log = logging.getLogger("booru") @@ -47,6 +48,12 @@ class E621Client(BooruClient): headers={"User-Agent": ua}, follow_redirects=True, timeout=20.0, + event_hooks={ + "request": [ + validate_public_request, + BooruClient._log_request, + ], + }, limits=httpx.Limits(max_connections=10, max_keepalive_connections=5), ) E621Client._e621_client = c