← All rules
mcp-scan rule
Deletion gap
data-controls-deletion-gapmediumWhat mcp-scan saw
This runs only after data-controls-pii fired. The scanner then searched the lowercased serialized server config for delete, remove, forget, destroy, wipe, or unlink. When none appear, it pushes this finding. Substring matching over the whole JSON, so tool names and env keys both count.
Why it fires
A deletion path is the one data control that cannot be added retroactively without touching storage, so its absence at design time is expensive later. The scanner reads the config as the server's public surface: if no tool, no argument, and no env key mentions deletion, the server most likely exposes no way to remove a record.
When this is a false positive
- The server stores nothing. A stateless query proxy has nothing to delete, but it still inherits the gate rule and then fails this check by construction.
- Deletion happens through the underlying system rather than through this server. A postgres MCP server that only reads has no delete tool, and the database has its own.
- The word test is loose in the other direction too: a tool named remove_label suppresses this finding even though it deletes no personal data.
- The gate rule may have fired on a keyword. If data-controls-pii matched the word 'password' in a description, this gap is about nothing.
How to fix it
- Check the data-controls-pii finding to see which categories triggered the family, and whether any of them correspond to stored data.
- If nothing is stored, this is not actionable. Address the gate rule instead.
- If data is stored, add a tool that deletes a record by id and name it plainly, for example delete_record. That both satisfies the check and is the actual control.
- Document where the delete path lives when it belongs to the underlying system rather than this server.
- To suppress the whole family for one server, add its config key to .mcp-scan-ignore.