Skip to content

fix: redact connection-string secrets from ConnectionEntry.lastError - #1501

Merged
gagik merged 2 commits into
mongodb-js:mainfrom
SyedAnas01:fix/list-connections-lasterror-redaction
Sep 10, 2026
Merged

gagik merged 2 commits into
mongodb-js:mainfrom
SyedAnas01:fix/list-connections-lasterror-redaction

Conversation

@SyedAnas01

Copy link
Copy Markdown
Contributor

ConnectionEntry.lastError is set from the raw driver/arg-parser error message when a connect attempt fails. That message can embed the connection string verbatim (for example, mongodb+srv://user:pass@ with no host, which throws Protocol and host list are required in "..." with the credentials still in it). lastError gets read back unredacted by summarizeConnection() and returned by list-connections, which takes no arguments and needs no confirmation.

The redaction in MongoDBToolBase.handleError() only covers the response for the call that's currently failing — it never touches ConnectionEntry.lastError, which is written one layer earlier in ConnectionEntry.connect().

This mostly matters for the preconfigured connection: it dials lazily, sits outside per-session scoping, and isn't removed from the store when a dial fails, so if MDB_MCP_CONNECTION_STRING is malformed this way, the raw string stays in lastError until the config is fixed — visible to any client calling list-connections, including other sessions in a shared HTTP deployment.

Fix: redact at the point of capture in ConnectionEntry.connect(), using Keychain.root.redact() — same pattern already used elsewhere in this codebase for driver errors that might carry secrets.

Test: added a regression test that fails a connect with a real (unmocked) @mongosh/arg-parser call against a truncated mongodb+srv:// string and asserts lastError doesn't contain the credential. Confirmed it fails without the fix, passes with it.

Related to GHSA-grqv-8942-f78m.

lastError is set from the raw driver/arg-parser error message on a
failed connect. That message can embed the connection string verbatim
(e.g. a malformed URI, missing host after the credentials), and
lastError is read back unredacted by summarizeConnection() and
returned by list-connections with no arguments and no confirmation.

The existing redaction in MongoDBToolBase.handleError() only covers
the response for the call that is currently failing, not this
persisted field. Redact at the point of capture instead, using the
root keychain the same way the rest of the codebase already does.

Mainly matters for the preconfigured connection: it's dialed lazily,
kept outside per-session scoping, and never removed from the store on
a failed dial, so a malformed MDB_MCP_CONNECTION_STRING leaves this
value sitting there until the config is fixed.
@SyedAnas01
SyedAnas01 requested a review from a team as a code owner September 8, 2026 12:36
@SyedAnas01
SyedAnas01 requested review from gagik and removed request for a team September 8, 2026 12:36
Comment on lines +137 to +139
// No mock needed here: a connection string with credentials but no host
// fails inside @mongosh/arg-parser before the driver is ever called, and
// the real arg-parser embeds the string verbatim in the thrown error.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this comment can be removed

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed, thanks.

@gagik

gagik commented Sep 10, 2026 •

Copy link
Copy Markdown
Collaborator

It's not a critical leakage but it is always good to harden these things so changes seem good to me 🙂

Please confirm that you have signed the MongoDB CLA. One small comment beyond that.

@SyedAnas01 SyedAnas01 changed the title Redact connection-string secrets from ConnectionEntry.lastError fix: redact connection-string secrets from ConnectionEntry.lastError Sep 10, 2026
@SyedAnas01

Copy link
Copy Markdown
Contributor Author

Hi @gagik, confirming I've signed the MongoDB CLA. Let me know if anything else is needed.

@gagik gagik added no-title-validation Add this label to disable the title check for this PR. type: bug type: chore and removed type: bug labels Sep 10, 2026
@gagik
gagik enabled auto-merge (squash) September 10, 2026 14:04
@gagik
gagik disabled auto-merge September 10, 2026 14:05
@gagik
gagik merged commit 1c10047 into mongodb-js:main Sep 10, 2026
43 of 45 checks passed
@gagik

gagik commented Sep 10, 2026

Copy link
Copy Markdown
Collaborator

@SyedAnas01 LGTM, thank you for your contribution!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

no-title-validation Add this label to disable the title check for this PR. type: chore

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants