Long-running tools have timeouts
Why it matters
A tool that calls fetch() with no timeout will hang indefinitely if the remote service is unresponsive — the MCP client freezes waiting for a result that never arrives. A tool that executes shell commands with no timeout can be kept running permanently by a hung subprocess, blocking the server for all clients. CWE-400 (uncontrolled resource consumption) is the mechanism; ISO 25010 performance-efficiency is the quality attribute violated. In agentic workflows where the AI chains multiple tool calls, a single hung tool halts the entire session.
Severity rationale
Medium because missing timeouts cause hangs under degraded network or process conditions rather than immediate failures, but the impact is a frozen session with no recovery path short of restarting the server.
Remediation
Add an AbortController timeout to every fetch() call and a timeout option to every shell command in tool handlers.
// src/tools/fetch.ts — 30-second timeout
server.tool('fetch_url', ..., async ({ url }) => {
const controller = new AbortController()
const timer = setTimeout(() => controller.abort(), 30_000)
try {
const res = await fetch(url, { signal: controller.signal })
clearTimeout(timer)
return { content: [{ type: 'text', text: await res.text() }] }
} catch (error) {
clearTimeout(timer)
const msg = (error as Error).name === 'AbortError'
? `Request timed out after 30s: ${url}`
: `Fetch failed: ${(error as Error).message}`
return { content: [{ type: 'text', text: msg }], isError: true }
}
})
DetectionPro
The detection method for this pattern is part of AuditBuffet Pro.
The full method (what to look for, pass and fail conditions, and how results get reported) ships inside the MCP Server Audit. The pattern definition, severity rationale, and remediation remain openly licensed under CC-BY-4.0.
External references
- cwe · CWE-400 — Uncontrolled Resource Consumption
- iso-25010:2011 · performance-efficiency
Taxons
History
- 2026-04-18·v1.0.0·Initial import from mcp-server·automated