Restrict MCP file-reading tools to an explicit directory allowlist
You will restrict which directories each MCP server can read, so a single exposed or misused server reaches less of your machine. Narrow reach limits the damage when something goes wrong.
- Inventory file accessFind every MCP server that can read files
- Set allowed rootsWrite the project directories as absolute paths
- Resolve and compareResolve symlinks and '..' before the allowlist check
- Test a denialConfirm a path outside the roots is refused
Why it matters
In SSE mode, mysql_mcp_server built its transport without security settings and bound to 0.0.0.0 with no authentication, so a network attacker or a DNS rebinding page could run execute_sql without credentials, with a CVSS score of 10.0 (GHSA-rqfv-2mw9-78g2 (opens external site)). The default stdio mode was not affected (GHSA-rqfv-2mw9-78g2 (opens external site)). The lesson for any server with file access is that exposure and reach multiply, so limit what each server can touch.
Steps
- Make a list of every MCP server you run that can read files, and note which directories each one can reach.
- Decide which project directories the agent actually needs. Write them down as absolute paths. Leave out your home directory, dotfile folders and credential stores.
- If a server has its own root or directory setting, set it to your allowed paths only. If it has no such setting, put a small check in front of its file reads that rejects any path outside the allowed roots.
- Resolve symbolic links and '..' segments before the check. Compare the real resolved path against the allowed roots, not the raw string the agent sent, so a link inside a project cannot point outside it.
- Prefer stdio for local servers. If a server must listen on the network, require authentication before you expose it. If you use mysql-mcp-server, upgrade to 0.4.2 or later (GHSA-rqfv-2mw9-78g2 (opens external site)).
- Test the restriction. Ask the agent to read a file outside the allowlist, such as a file in your home directory, and confirm the call is refused. Then confirm a file inside an allowed root still works.
- Review the list whenever you add a project or move where credentials live.
Common mistakes
- Allowing the home directory 'just in case'. That brings back the access you were trying to remove.
- Checking the path string but not the resolved path, which lets symlinks and '..' segments escape the root.
- Assuming a server is isolated because it runs locally. Binding to 0.0.0.0 without authentication exposes it to other machines.
- Skipping the denial test. A server can look configured and still read anything if the check is never exercised.
Checklist
0 of 8 done