fix(CLI-40): scrub the credential from the redacted error's structured reply, route MXACCESS_FAILURE to MxAccess (Rust), fix Go Subscribe terminal-error drop

Code-review follow-up on the CLI-40/41/44 branch.

ISSUE 1 (all five, critical): the message-only scrub still leaked the
server-echoed credential through the redacted error's structured reply accessor
(.NET Reply/Statuses, Java reply()/protocolStatus(), Go MxAccessError.Reply via
errors.As, Rust reply()/into_reply(), Python raw_reply). The redacted error now
carries a scrubbed clone of the reply (protocol_status.message,
diagnostic_message, statuses[].diagnostic_text), with per-language tests asserting
the reply accessor no longer contains the credential.

ISSUE 2 (Rust, critical): ensure_command_success routed MXACCESS_FAILURE to
Error::Command (unlike the other four clients), bypassing attach_secrets and
leaking via derived Debug/Display. MXACCESS_FAILURE now routes to Error::MxAccess,
fixing the cross-client inconsistency.

ISSUE 3 (Go, important): the CLI-44 terminal send was unconditionally
non-blocking, dropping a genuine terminal error under a full buffer on the
never-drop SubscribeEvents path. It is now reserved-slot-non-blocking only for the
cancel-on-overflow path and blocking for the never-drop path.

New shared fixture authenticate-user.echoed-credential-mxaccess-failure.reply.json
wired into all five suites. Minors: whitespace-secret guard on .NET/Java redact
helpers; Java preserves exception subtype on redaction; redaction-helper unit
tests (Go/Java/.NET). Docs (ClientBehaviorFixtures.md, ClientLibrariesDesign.md)
updated to make the structured-field claim true.
This commit is contained in:
Joseph Doherty
2026-08-07 07:04:56 -04:00
parent dc7fd16dd5
commit 0d874f91ee
25 changed files with 1190 additions and 88 deletions
+9 -3
View File
@@ -138,10 +138,16 @@ secured payloads route through each client's secret-redaction seam so they never
reach logs, exception text, or `ToString`/`Debug`/`Display` — the value is carried
only on the wire. In addition to that by-construction guarantee (exceptions carry
reply-derived text, not the request), every client scrubs the **exact** secret
values it was called with from any surfaced error text as defense-in-depth, so a
values it was called with from any surfaced error as defense-in-depth, so a
gateway or MXAccess diagnostic that echoes a credential back cannot leak it
(CLI-40). Each client's test suite asserts a distinctive credential is absent
from any surfaced error and that the redaction marker is present.
(CLI-40). The scrub covers **both** the rendered message and the structured reply
the error still exposes (`protocolStatus.message`, `statuses[].diagnosticText`,
`diagnosticMessage`): the redacted error carries a scrubbed clone of the reply so
a logger dumping the exception's structured fields cannot reintroduce the leak.
This holds regardless of whether the reply is coded `OK` (with a failing HRESULT)
or `MXACCESS_FAILURE` — every client routes both to its MXAccess error type. Each
client's test suite asserts the distinctive credential is absent from both the
surfaced message and the exposed reply, and that the redaction marker is present.
Shipped in all five clients (.NET / Go / Rust / Python / Java).