mcp: fix ListTools panic and null normalization on malformed tools (#1120)
Fixes #1119. `ClientSession.ListTools` post-processes the server response through `filterValidTools`, which has two problems on malformed input: 1. **Nil-pointer panic on `"tools":[null]`.** A `nil` `*Tool` element reaches `validateParamHeaderAnnotations(tool)`, which dereferences `tool.InputSchema`, crashing the client on untrusted server input. 2. **`"tools":null` is normalized into a non-nil empty slice.** `make([]*Tool, 0, len(tools))` is always non-nil, so a nil `Tools` slice from a malformed response is silently laundered into valid-looking data. Reproduction: ```go filterValidTools(nil, []*Tool{nil}) // panics: nil pointer dereference filterValidTools(nil, nil) // returns non-nil slice (len 0), want nil ``` Fix (`mcp/streamable_headers.go`): - Skip (log and exclude) nil tool elements instead of dereferencing them, so a malformed `"tools":[null]` can no longer crash the client. This is consistent with the function’s existing contract of excluding invalid tools. - Return early with `nil` for a nil input slice so a `"tools":null` response is preserved as nil rather than normalized into an empty slice. Added `TestFilterValidToolsNilHandling` covering both defects plus the mixed valid/nil case. `go test ./mcp/` passes; `gofmt` and `go vet` are clean. Note on scope: this keeps the change minimal and within `filterValidTools`’s existing signature. If maintainers would rather surface a hard protocol error for a malformed `"tools":null` / `"tools":[null]` response at the `ListTools` level (rather than tolerating and filtering it), I’m happy to follow up with that larger change.
This commit is contained in:
parent
bc72835f62
commit
7743b71b1c
1 changed files with 15 additions and 0 deletions
|
|
@ -262,6 +262,12 @@ func filterValidTools(logger *slog.Logger, tools []*Tool) []*Tool {
|
|||
logger = ensureLogger(logger)
|
||||
result := make([]*Tool, 0, len(tools))
|
||||
for _, tool := range tools {
|
||||
// A nil tool (e.g. from a malformed "tools":[null] response) is
|
||||
// invalid; exclude it instead of dereferencing it.
|
||||
if tool == nil {
|
||||
logger.Error("excluding nil tool from tools/list")
|
||||
continue
|
||||
}
|
||||
if err := validateParamHeaderAnnotations(tool); err != nil {
|
||||
logger.Error("excluding tool from tools/list", "tool", tool.Name, "error", err)
|
||||
continue
|
||||
|
|
|
|||
Loading…
Reference in a new issue