fix(server): sanitize error responses to prevent stack trace exposure#1187
Open
cliffhall wants to merge 1 commit intomodelcontextprotocol:mainfrom
Open
fix(server): sanitize error responses to prevent stack trace exposure#1187cliffhall wants to merge 1 commit intomodelcontextprotocol:mainfrom
cliffhall wants to merge 1 commit intomodelcontextprotocol:mainfrom
Conversation
Replace raw error objects passed to res.json() with generic sanitized messages so internal error details are not leaked to clients. Full errors continue to be logged server-side via console.error. Also adds a missing return in the /sse ECONNREFUSED branch, which previously fell through and attempted a second response after headers had already been sent. Resolves CodeQL js/stack-trace-exposure alerts in server/src/index.ts. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR addresses CodeQL js/stack-trace-exposure findings in the server by ensuring Express routes no longer serialize raw caught Error objects into HTTP JSON responses, reducing the risk of leaking stack traces/internal details to clients.
Changes:
- Added a
sendErrorResponse(res, status, message)helper to return sanitized{ error: "<message>" }responses. - Replaced multiple
res.status(...).json(error)call sites across/mcp,/stdio,/sse,/message, and/configwith sanitized responses. - Fixed a
/sseerror-path fallthrough by adding a missingreturnafter responding in theECONNREFUSEDbranch.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
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.
Summary
Resolves the 11 open CodeQL
js/stack-trace-exposurealerts inserver/src/index.ts. Each was a spot where a raw caughterrorobject was handed tores.json(...), which can leak internal error details (including stack-trace-derived data) to clients.The fix introduces a small
sendErrorResponse(res, status, message)helper that returns a generic sanitized JSON body, and replaces every flagged call site with it. Full error objects continue to be logged server-side via the existingconsole.errorcalls, so debuggability is unchanged.Alerts addressed
sendProxiedUnauthorizedfallback)Incidental fix
The
/ssehandler'sECONNREFUSEDbranch was missing areturn, so after sending its 500 it fell through to the genericError in /sse routebranch and attempted a second response on the already-sent headers. Added the missingreturnsince the sanitization pass touched those lines anyway.Behavior changes
Errorobjects on 4xx/5xx failures from/mcp,/stdio,/sse,/message, or/config. They now receive{ "error": "<generic message>" }.sendProxiedUnauthorizedno longer takes anerrorparameter — the upstream-capture path was already ignoring it, and the fallback path now returns a plain{ error: "Unauthorized" }instead of JSON-encoding the caught exception.console.errorbefore responding.Test plan
npm run build-serverpasses (tsc)npm run prettier-fixclean/mcpto an unreachable URL) returns{ "error": "Internal server error" }rather than a serialized exception, and thatconsole.errorstill logs full details server-sideWWW-Authenticateheader and body (the non-fallback path insendProxiedUnauthorized)🤖 Generated with Claude Code