refactor(redact): consolidate CDP-URL log redaction into one chokepoint

The session-log fix (browser_tool._sanitize_url_for_logs) and the
supervisor attach-timeout fix (CDPSupervisor.start) both composed the
same three redactors (redact_sensitive_text -> _redact_url_query_params
-> _redact_url_userinfo) to mask CDP endpoint credentials. Two copies of
one policy drift: tune one site (e.g. add fragment masking) and the other
silently re-leaks.

Promote that composition to a single public helper redact_cdp_url() in
agent/redact.py -- the one place the CDP-URL redaction policy lives -- and
route both call sites through it (_sanitize_url_for_logs becomes a thin
wrapper; the supervisor imports the helper instead of re-composing the
private redactors). Add direct unit tests for the seam covering query
tokens, multiple credentials, userinfo passwords, plain-URL passthrough,
non-string/exception coercion, and None.

No behavior change at the call sites; both leak paths remain closed.
This commit is contained in:
kshitijk4poor 2026-07-01 13:30:36 +05:30 committed by kshitij
parent 265da9cadb
commit c626dded13
4 changed files with 76 additions and 26 deletions

View file

@ -65,11 +65,7 @@ import requests
from typing import Dict, Any, Optional, List, Tuple, Union
from pathlib import Path
from agent.auxiliary_client import call_llm
from agent.redact import (
redact_sensitive_text,
_redact_url_query_params,
_redact_url_userinfo,
)
from agent.redact import redact_cdp_url
from hermes_constants import agent_browser_runnable, get_hermes_home
from utils import env_int, is_truthy_value
from hermes_cli.config import DEFAULT_CONFIG, cfg_get
@ -244,21 +240,13 @@ _command_timeout_resolved = False
def _sanitize_url_for_logs(value: object) -> str:
"""Mask secrets in logged browser endpoint URLs and URL-like errors.
The global ``redact_sensitive_text`` deliberately passes web-URL query
params and ``user:pass@`` userinfo through unmasked (OAuth callbacks,
magic-link / pre-signed URLs the agent is meant to follow see the
web-URL note in ``agent/redact.py``). CDP discovery endpoints are NOT
such a workflow: their query-string tokens and userinfo passwords are
pure credentials that must never reach the logs. So at these log sites
we opt INTO the URL redactors that the global pass leaves off, reusing
the shared ``redact.py`` helpers rather than a second regex.
Thin wrapper over :func:`agent.redact.redact_cdp_url`, which is the single
source of truth for CDP-URL log redaction. Kept as a local name because
several browser-tool log sites reference it; the redaction policy itself
lives once in ``redact.py`` so the browser tool and the CDP supervisor
cannot drift apart.
"""
text = redact_sensitive_text(value)
if not text:
return text
text = _redact_url_query_params(text)
text = _redact_url_userinfo(text)
return text
return redact_cdp_url(value)
def _get_command_timeout() -> int: