From 5699aa9dde74df86f21bed3a301969fb7c44e1ea Mon Sep 17 00:00:00 2001 From: disqualifier Date: Sun, 9 Aug 2026 02:10:30 -0400 Subject: [PATCH] fix: mask the provider reset url before logging it net.reset() logged the full reset_url at INFO on the success path; a provider reset url can carry a rotation token in its query string, so this leaked it to logs. strip the query + fragment before logging (stdlib urlsplit, no new dependency - the core stays dependency-free) so the token cannot reach a log sink; scheme/host/path are kept for diagnostics. Signed-off-by: disqualifier --- src/aioproxies/net.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/aioproxies/net.py b/src/aioproxies/net.py index a5f3da4..7e1cf25 100644 --- a/src/aioproxies/net.py +++ b/src/aioproxies/net.py @@ -6,11 +6,24 @@ calling a function without it raises a clear error. """ import logging from typing import Optional, Union +from urllib.parse import urlsplit, urlunsplit from .proxy import Proxy, to_proxy log = logging.getLogger(__name__) + +def _safe_url(url: str) -> str: + """strip query + fragment from a url for logging - a provider reset url can carry a + rotation token in its query/path; this drops the query/fragment (the usual token spot) + so the log line can't leak it. falls back to the raw url only if it won't parse""" + try: + parts = urlsplit(url) + except ValueError: + return url + return urlunsplit((parts.scheme, parts.netloc, parts.path, "", "")) + + try: import aiohttp @@ -55,7 +68,7 @@ async def reset(reset_url: str, *, timeout: float = 15.0) -> bool: async with aiohttp.ClientSession(timeout=t) as session: async with session.get(reset_url) as resp: ok = resp.status == 200 - log.info("proxy reset %s -> %s", reset_url, resp.status) + log.info("proxy reset %s -> %s", _safe_url(reset_url), resp.status) return ok except Exception as exc: log.warning("proxy reset failed: %s", exc)