Tool Definition & Lifecycle
An MCP tool that performs irreversible operations such as file deletion, database mutation, or HTTP DELETE executes without requiring explicit user approval, allowing a single LLM decision to cause unrecoverable data loss.
Missing authorization check (CWE-862) on destructive operations — specifically, the absence of any confirmation gate before invoking sinks such as fs.unlinkSync, os.remove, shutil.rmtree, DROP TABLE, DELETE FROM, or HTTP DELETE/PUT/PATCH. The tool accepts input and immediately executes the destructive action with no dry-run path, idempotency key, or elicit() round-trip to obtain explicit human approval.
MCP tools are invoked autonomously by LLMs that may chain multiple tool calls within a single reasoning step, meaning a misinterpreted instruction or prompt-injected directive can trigger deletion before any human reviews the action. Unlike traditional web APIs where a human explicitly clicks a confirm button, MCP collapses the confirmation UX into the LLM's own judgment, removing the human from the loop by default. Tool composition amplifies this risk: a file-listing tool followed by a file-removal tool can be orchestrated end-to-end by the model with no natural pause for user intervention.
import * as fs from "fs"; |
server.tool( |
"remove_workspace_file", |
"Remove a file from the workspace.", |
async ({ path }: { path: string }) => { |
fs.unlinkSync(path); |
return { ok: true }; |
}, |
); |
import * as fs from "fs"; |
server.tool( |
"remove_workspace_file", |
"Remove a file from the workspace.", |
async ({ path }: { path: string }, { elicit }) => { |
const ack = await elicit({ prompt: `Permanently delete ${path}? This cannot be undone.` }); |
if (!ack.confirmed) return { ok: false, reason: "User cancelled." }; |
fs.unlinkSync(path); |
return { ok: true }; |
}, |
); |
MCPSafe performs a file-scoped conjunction check: it confirms both the presence of a tool registration call (server.tool / @mcp.tool) and at least one destructive sink (fs.unlink, os.remove, shutil.rmtree, DROP\s+TABLE, DELETE\s+FROM, TRUNCATE, UPDATE\s+\S+\s+SET, HTTP DELETE/PUT/PATCH methods, subprocess.run, exec, or spawn), then flags the file only when none of the confirmation patterns — elicit(), dry_run parameter, dryRun flag, or idempotency_key — appear anywhere in the same file.
See the full threat catalog for every documented detection.
MCPSafe runs this check — and every other rule in the catalog — on any MCP server you paste in.
Scan now