e09ff88d02
Review of the salvage found the timeout-message redaction left the more common failure mode unguarded: when the first websockets.connect(cdp_url) fails (bad URI / refused / TLS), the raw websockets exception -- which embeds the full cdp_url incl. ?token= and user:pass@ -- is stashed as _start_error and re-raised verbatim by start(), and two reconnect logger.warning sites log the same raw exception. Add a module-level _redact_cdp_error_text() chokepoint (delegating to agent.redact.redact_cdp_url) and route all four supervisor egress points through it: - start() TimeoutError message (already covered; kept) - start() _start_error re-raise -> now raises a redacted RuntimeError with 'from None' so no secret leaks via message OR traceback cause chain - connect-failed and session-dropped reconnect warnings Guard tests assert the re-raised message is redacted for both token and userinfo, the raw cause is suppressed, and the helper preserves non-secret context (host/reason). Verified with a mutation check: reverting to the raw 'raise err' fails the new tests. Correct the redact_cdp_url docstring to scope its guarantee to direct-URL redaction and point exception callers at the supervisor helper.