MCP-003 Overbroad filesystem root
MCP filesystem servers (the @modelcontextprotocol/server-filesystem
family) grant the model read / write reach across the directory the
host process points them at. Mounted at ~/Documents they expose
every document on the machine. Mounted at $HOME they expose the
whole user home including .ssh, .gnupg, browser profiles, and
session-token caches. Mounted at / they expose the entire
filesystem the host process can reach. Even when the user trusts
the model, a single prompt-injection turns "this MCP can read
files" into "this MCP can exfiltrate everything".
What Vulkro detects
Rule fires when a filesystem-class MCP server has a path argument that falls into one of two classes:
- Root: literal
/, literal$HOME/~/${HOME}, the unexpanded user-home forms/Users/<name>and/home/<name>with no further path segment. Severity:High. Evidence weight:0.8, sourcePattern. - Shallow: a single-segment directory under home (
~/Documents,~/Desktop,$HOME/work) or under root (/tmp,/var). Severity:Medium. Evidence weight:0.5, sourceHeuristic.
The detector recognises a filesystem-class server by the package
name in args:
server-filesystem(the official@modelcontextprotocol/server-filesystem)filesystem-servermcp-server-fsserver-fs
Non-filesystem servers are skipped: random server args may legitimately be paths to configuration files, and over-firing there would be the wrong shape.
Path classification is intentionally based on the literal text. The
detector does NOT expand ~ against the running user's home: the
finding is about the declared scope, not what the OS would resolve
to. A literal / mount IS the root mount regardless of who runs
the host.
Evidence signal: mcp-server-overbroad-fs-root. Confidence: High
for the root class, Medium for the shallow class.
Non-compliant config
{
"mcpServers": {
"fs-root": {
"command": "npx",
"args": [
"/"
]
},
"fs-home": {
"command": "npx",
"args": [
"$HOME"
]
},
"fs-shallow": {
"command": "npx",
"args": [
"~/Documents"
]
}
}
}
Compliant config
{
"mcpServers": {
"fs": {
"command": "npx",
"args": [
"/Users/me/work/this-project"
]
}
}
}
The mount is scoped to a single project directory the model genuinely needs reach into.
Remediation
- Narrow the mount to the smallest directory the model needs.
~/work/<project>is almost always the right answer;~and/almost never are. - If multiple projects need reach, declare one MCP server entry
per project rather than mounting
~/workas a whole. The detector treats two-segment-or-deeper paths as adequately scoped. - For workflows that genuinely need broad reach (system administration scripts, machine-wide search), document the trust assumption in the host config or your team's MCP setup notes so the next reviewer doesn't have to rediscover it.
See also
vulkro mcp-audit- parent CLI command.- MCP-001 - the pin-shape rule (filesystem servers are upgraded to High when unpinned because broad-mount + unpinned amplifies the blast radius).
- Confidence model - what
High,Medium,Lowmean for MCP findings.