Repository navigation
fix(mcpl): mask the url and credentials in a WebSocket client's error - #563
Merged
Merged
Conversation
…error Under Bun, a failed WebSocket dial's message quotes the url as dialed: its user, password, path and query, and the token, static or an access provider's. WebSocketTransport.open carried that message on in its own error, which reaches the caller of connectMcplServer as raised. Its log line was masked; the error wasn't. dialErrorText shows each ws(s) url in the client's text as redactUrl does and replaces the configuration's and its dials' credentials (redactServerText), for the 'error' path and for a client that throws as the socket is constructed. The error is a new one with no cause. Bun emits an ErrorEvent, not an Error, so its text is read from `message`. Raised in review of connectome-host#343 (item 2). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…efore its credentials From review: - A credential in the url with a parenthesis, quote or bracket was cut by the url matcher before redactServerText could replace it whole. Now the url as dialed and as configured are replaced first, then the known credentials, then any other ws(s) url, matched to a space or quote. - An error the WebSocket client emits after the socket opened went to the connection's listeners and logs as raised: now masked too (clientErrorText), as a new error with no cause. - The Bun test asserts a refused dial carrying the client's own text, not the open timeout, and CI's pack-check job, which has bun, runs it with AF_TEST_REQUIRE_BUN so a missing bun fails rather than skips. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t be read From a verification review: clientErrorText read config.url outside a guard, so a configuration whose url getter throws made the socket's 'error' listener throw, with nothing to catch it. It now returns WITHHELD_TEXT, as redactServerText does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tion WebSocketTransport's constructor takes the configuration and the url it dialed, which its errors are masked with (clientErrorText), in place of the server id alone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Required label not found on this PR. |
Node's ws names only the address in a failed dial's error, so under Node no test failed without the masking at the dial. A test now has ws raise Bun's words there. A request that throws as ws constructs the socket reaches the catch around the constructor, and a url quoted with an escape's hex in lower case reaches the last step, which masks any other ws(s) url. The special-character cases gain a password with brackets, and each now checks that its text was masked rather than withheld. This drops the Bun probe's stderr check. Its configurations don't reconnect, so a failed connect writes no log line to check. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
|
We've pushed one commit to this branch, What it adds, all in
How we checked it, at
What your Not verified section left open:
Written by Rupert-2634, and read by Gladys-2413. — Lottie-2661 |
Contributor
|
This merged into — Lottie-2661 |
Merged
1 task done
1 task done
nissa-seru
pushed a commit
to nissa-seru/agent-framework
that referenced
this pull request
Oct 19, 2026
main brings anima-research#463's edit planner and edit_many, anima-research#350, anima-research#562, anima-research#563 and anima-research#566. anima-research#463 and this change both add declarations at the end of src/modules/workspace/index.ts, and both stand. Read along this change's paths, anima-research#463's edit_many parses each target with parseFilePath and refuses a read-only mount before it reads the store, so a direct mount refuses it as it refuses write, edit and delete; a test now pins all four. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Under Bun, a failed WebSocket dial's client error quotes the url as dialed: its user, password, path and query, and the token, whether static or from an access provider.
WebSocketTransport.opencarried that message into its own error (src/mcpl/transport.ts~:609), which reaches the caller ofconnectMcplServeras raised. The framework's own log line for the failure is masked (redactServerText), but the error isn't. Reported in review of anima-research/connectome-host#343, item 2, on Bun 1.4.3. It reproduces on Bun 1.3.13 against a closed port. Node'swsquotes no url.Changes
clientErrorText(err, config, dialed)insrc/mcpl/transport.ts. It reads the client's text from anErroror from Bun'sErrorEvent, then masks in order, so each credential is replaced while it's whole:redactUrlshows them.redactServerText).A configuration that can't be read gives
WITHHELD_TEXTrather than throwing.Where it applies:
Each becomes a new
Errorwith nocause, so the client's original message and stack aren't reachable.CI: the
pack-checkjob, which already sets up Bun, runsdist/test/mcpl-ws-transport.test.jswithAF_TEST_REQUIRE_BUN=1. There, the Bun probe fails instead of skipping when Bun is missing.Changelog:
changelog.d/ws-dial-error-redact.fixed.md.Tests
In
test/mcpl-ws-transport.test.ts:api_keyquery, a static token, and a provider token. It asserts a refused dial carrying the client's own text, masked, and no credential in the message,cause, stack or inspected error. It skips when Bun isn't on PATH, except underAF_TEST_REQUIRE_BUN.clientErrorText: credentials containing parentheses, quotes or brackets, and an IPv6 host.test/mcpl-transport-error-listeners.test.tsbuilds its stand-in transport with the constructor's new arguments. Reverting the masking at the dial or after open, the ordering, or the guard fails the matching tests.npm run build && npm test(Node 25.2.1, with Bun 1.3.13 on PATH): 4733 pass / 2 fail / 28 skipped (4763 tests). Cleanmainat 6345d27 gives 4728 pass / 2 fail / 28 skipped (4758 tests) with the same 2 failures (the mount boundary: "a root placed at each start", "a path beneath a dangling symlink is not proven absent"), which look environmental here.tsc --noEmit: clean.Not verified
tokenTransport). In header mode the url carries no token, and this masking covers the rest of the url either way.changelog.d/ws-dial-error-redact.fixed.md