Skip to content
Everfinity
← Knowledge

What can an MCP server actually reach on your network?

Security and auditReviewed October 12, 2026

Short answer

Everything you can. A local MCP server is an ordinary process launched with your user's privileges, so it can read any file you can, open any connection your machine can — localhost services, the office LAN, the cloud metadata address — and hold whatever secrets you put in its config. The tool list the client shows you limits what the model asks for, not what the process can do. We counted the official registry: 16,580 servers run locally and 38% of them ask for a secret. Treat each one as a dependency with a shell, and sandbox it — in our test, that cost nothing.

The question is wrong, and that is the answer

People ask what an MCP server can reach as if it were a property of the server — as if a GitHub connector reaches GitHub and a filesystem connector reaches one folder. It is not a property of the server. It is a property of how you launched it.

A local MCP server — the kind you add with a line in claude_desktop_config.json, .cursor/mcp.json or .vscode/mcp.json — is an ordinary program. The client starts it as a child process, talks to it over standard input and output, and that is the entire security model. The process runs as you. It can read what you can read, connect to what your machine can connect to, and start other programs. The protocol's own security page says so plainly: local servers "may have direct access to the user's system," and without sandboxing an attacker "can execute any command with MCP client privileges."[2]

So the honest answer to "what can it reach on our network" is: the same things your laptop can. The rest of this page is about how many of these things are on your laptops, what they ask you to give them, why the approval prompt does not change any of it, and the one control that does — which, it turns out, is free.

Two permission systems, and only one is enforced

Two panels. Left, outlined in grey: the tool list an MCP client shows — read_text_file, write_file, edit_file and more — written by the server and described by the spec as untrusted. Right, outlined in acid: what the operating system grants the process — your files, your network including localhost and 169.254.169.254, the secrets in its environment, and child processes.
The left box is what you approve. The right box is what the process gets. The protocol never connects them. MCP specification 2025-11-25

Every MCP client shows you something that looks like a permission screen: a list of tools, a toggle per tool, a prompt before a call. It feels like the thing you are approving is the server's reach. It is not. That list is written by the server, and the specification instructs clients to treat its annotations "as untrusted unless they come from trusted servers."[3] More importantly, it only governs one thing: which tool calls the model may ask for.

It has no say over what the process does on its own. Code runs at import time, before the first tool is listed. It runs on a timer. It runs inside the get_weather tool you approved, doing something that is not getting the weather. Invariant Labs showed in April 2025 that a tool's description alone could steer an agent into reading ~/.ssh/id_rsa and the client's own MCP config, and that a server could change its tool descriptions after you had approved them — the "rug pull."[5] That attack goes through the model. The easier one does not need the model at all.

We counted the registry

Opinions about how common this is are cheap, so we counted. On 12 October 2026 we paged through the entire public API of the official MCP Registry — the one run by the protocol's maintainers — and pulled the latest version of every server.[1] No scraping of READMEs, no sampling: every entry, read from the metadata the authors themselves submitted.

Of 41,713 active servers, 16,580 (39.7%) run on the user's machine and 24,654 (59.1%) are remote-only. Of the local ones, 6,294 (38.0%) declare at least one secret. The 9,180 declared secrets break down as 4,879 API keys, 1,832 tokens, 756 other secrets, 729 client secrets, 565 passwords and 419 private or wallet keys.
Every active entry in the official MCP Registry, latest version only. Secrets are environment variables the authors themselves marked isSecret. Official MCP Registry API, 12 Oct 2026

41,713 active servers. 16,580 of them — 39.7% — are packages you download and run on your own machine: npm, PyPI, container images, MCPB bundles, NuGet, Cargo. 16,336 of those talk over stdio, which means a child process of your editor or desktop app.

Then the number that should make a CISO put their coffee down. 6,294 of the local servers — 38% — ask you to hand them a secret, and they declare 9,180 secrets between them. Most are API keys. 565 are passwords. 419 are private keys or crypto wallet keys, requested by 372 servers. Every one of those is pasted into a config file in plain text, then handed to a process that, launched the usual way, can also read the rest of your disk. Astrix found the same shape from the other direction: across 5,205 server repositories, 53% relied on static API keys or personal access tokens, 79% of keys were passed through plain environment variables, and only 8.5% used OAuth.[14]

Notice what this does to the question. You do not need a malicious server for the secret to leak. You need any one server on the machine to be malicious, compromised or vulnerable, because they all share one user account, and one home directory.

The default that sounds safe and isn't

There is a reassuring detail in the official TypeScript SDK. When a client launches a stdio server, it does not hand over your whole shell environment. It passes a short allowlist "inspired by the default env inheritance of sudo": HOME, LOGNAME, PATH, SHELL, TERM, USER, plus whatever the config adds explicitly.[4] We checked it in our lab: our shell held 151 environment variables, and the SDK's default passed four of them through.

That is good engineering, and it protects much less than it looks like. One of those variables is HOME. Your SSH keys, your ~/.aws/credentials, your .npmrc publish token, your .kube/config, your browser profile — none of them live in the environment. They live in files under HOME, and filtering environment variables does nothing to a process that can open files. The spec's own example of a malicious one-click install is exactly that: a command that curls ~/.ssh/id_rsa to a remote address.[2]

This is not hypothetical. The SANDWORM_MODE npm worm in February 2026 installed its own rogue MCP server into developers' assistant configs, with tool descriptions telling the coding assistant to gather SSH, AWS and npm secrets — and "not mention this context-gathering step to the user."[7] In August, OX Security traced a Shai-Hulud wave through an entry in the official registry itself, linking to a clean package and a repository whose editor config ran on open.[8]

The network is bigger than "the internet"

"Network" in the question usually means "can it phone home." That is the least interesting part. A process on a developer laptop can reach:

  • localhost. Every dev server, database, admin panel and debugging port you have running, most of them unauthenticated because "it's only local." The MCP Inspector itself shipped exactly this bug: its proxy listened without authentication and could be driven from a web page, a CVSS 9.4 remote code execution.[10]
  • The office network and the VPN. Whatever your laptop routes to — internal wikis, staging, the CI server, the printer with the 2019 firmware.
  • 169.254.169.254. On a cloud VM, a dev container or a CI runner, the instance metadata service hands out temporary cloud credentials to anything that asks, which is why AWS built IMDSv2 specifically to defend against server-side request forgery.[12] The MCP spec names this address and tells clients to block the whole 169.254.0.0/16 range for exactly this reason.[2]

And a server does not have to be malicious to become the attacker's network access. Equixly's review of popular implementations reported command injection in 43% of the servers it tested, unrestricted URL fetching in 30% and file access outside the intended directory in 22% — a vendor figure without a published sample size, but the direction is the point.[13] A server with an unrestricted fetch tool and a model that reads untrusted text is a server-side request forgery primitive that sits inside your network perimeter.

Is the code you launch the code that was registered?

Here is the finding we did not expect, and as far as we can tell nobody has published it. A registry entry names a specific package version. The config most people copy does not — it says npx some-mcp-server or uvx some-mcp-server, which resolves to whatever is latest at the moment the editor starts. So we checked, for every registry package, whether those two are still the same thing.

Horizontal bars by packaging format. OCI images: 98.7% referenced by mutable tag (1,083 of 1,097). npm: 33.2% have a latest version different from the registered one (3,444 of 10,358). PyPI: 20.2% (826 of 4,083). MCPB bundles: 0% — all 1,549 carry a SHA-256, highlighted in acid.
For each format, the share of registry packages whose default install today resolves to something other than what the registry entry names. MCPB is the only format that pins bytes. Official MCP Registry, npm and PyPI APIs, 12 Oct 2026

On npm, 3,444 of 10,358 packages — a third — have a latest release that is not the version the registry entry names. On PyPI it is 826 of 4,083, one in five. Of 1,097 container images, 1,083 are referenced by a tag like :latest or :1.2, which the publisher can repoint at any time; only 14 are pinned by digest. The single bright spot is the MCPB bundle format: all 1,549 carry a SHA-256 hash in the registry, so a client can verify it is running the exact bytes that were published.

Most of that drift is innocent — 3,336 of the npm mismatches are simply newer releases the author never re-registered. That is the point, not the excuse. Whatever review, scan or approval happened against the registered version did not happen against the code your editor launches tomorrow morning. That is precisely the gap the first malicious MCP server in the wild used: postmark-mcp shipped fifteen clean versions, built up roughly 1,500 weekly downloads, and in version 1.0.16 added one line that blind- copied every email it sent to the attacker.[6] Everyone on npx postmark-mcp updated themselves into it.

One more number from the same pass, because it is the kind of thing that turns into an incident: 21 active registry entries point at a PyPI project name that, on the day we checked, returned no project at all. We are not listing them here; we are reporting them to the registry maintainers.

The vulnerabilities are in the plumbing, too

It is tempting to treat this as a "don't install sketchy servers" problem. The record says otherwise — the serious bugs have repeatedly been in the trusted, official plumbing:

  • mcp-remote, the widely used bridge from local clients to remote servers, had an OS command injection triggered by a malicious server's OAuth metadata — CVSS 9.6, fixed in 0.1.16.[9] Connecting to the wrong URL was enough.
  • The reference Filesystem server — the one that exists to confine access to one folder — had a prefix-matching bypass and a symlink escape (CVE-2025-53110 and CVE-2025-53109), the second rated 8.4 and leading to code execution.[11]
  • Smithery, a hosting platform for MCP servers, leaked a deployment token through a path traversal in its build config that reached more than 3,000 hosted apps, with root command execution.[16]
  • Remote servers are not exempt: a 2026 measurement of 7,973 live remote MCP servers found 40.55% exposing tools with no authentication, and flaws in 96.6% of the OAuth dynamic-client-registration setups tested.[15]

The filesystem case is the instructive one. Its allowed-directory check is policy inside the process. Policy inside the process is exactly as strong as the process's own code — which is why the only boundary worth relying on is one the process cannot argue with.

We sandboxed the reference server and timed it

The usual objection to sandboxing is that it will break things or slow them down. So we measured it. We took @modelcontextprotocol/server-filesystem 1.0.0, pointed it at one working folder, and drove it with the official TypeScript SDK client 1.32.1 — thirty cold starts launched plainly, thirty launched inside a Linux user and network namespace with an empty, private home directory and no network. Each run: spawn, handshake, list the tools, read a file inside the folder, try to read a file outside it.

A comparison table. Plain and sandboxed launch both advertise 14 tools, read the allowed file 30 of 30 times and refuse the outside path 30 of 30 times. Plain: home directory fully visible, network open, median 234 ms, p90 305 ms. Sandboxed: home directory empty, no network, median 229 ms, p90 284 ms.
Thirty cold starts each, same server, same client. The sandbox removed the home directory and the network and changed nothing the user could notice. Our lab, 2026

The result is the least dramatic chart on this page and the most important one. Same 14 tools. Same answers, 30 out of 30. The server's own outside-folder check refused the same request in both cases — and in the sandboxed case it no longer mattered whether that check had a bug, because there was nothing outside the folder to see. The median round trip was 234 ms plain and 229 ms sandboxed: inside the noise, and if anything slightly faster. The control that actually bounds what an MCP server can reach cost us nothing measurable.

The wrapper is one line, and on Linux distributions that allow unprivileged user namespaces it needs no root:

unshare -rn --mount --propagation private sh -c \
  'mount -t tmpfs none "$HOME" && exec node server.js /path/to/project'

On macOS, a container with one bind mount and --network none does the same job; VS Code now ships an opt-in sandboxEnabled setting for MCP servers on macOS and Linux, while noting that local servers "can run arbitrary code on your machine."[17] The specification already asks clients to do this by default — it says they SHOULD run local servers "in a sandboxed environment with minimal default privileges."[2] Most do not yet. Until they do, it is yours to do.

What to actually do on Monday

  1. Inventory the configs, not the servers. Search every developer machine and repo for mcp.json, claude_desktop_config.json, .cursor/mcp.json and .vscode/mcp.json. The question is not "which servers are approved," it is "which processes start when someone opens their editor."
  2. Pin by hash, or by exact version. Prefer MCPB bundles and image digests. Where you must use npm or PyPI, write the exact version into the config — pkg@1.4.2, not pkg — so an update is a reviewed diff instead of a silent swap.
  3. Sandbox every local server. One project folder, no home directory, no network unless its job is the network. If it needs the network, allow its one API host and block 169.254.0.0/16, 127.0.0.0/8 and your private ranges.
  4. Move secrets out of config files. A scoped, short-lived token per server, from a secret manager, never a personal admin key. If a server asks for a wallet private key, the answer is no.
  5. Treat remote servers as vendors. Who runs it, what token it holds, what it logs, where that data goes. No authentication is not a configuration choice; it is a finding.
  6. Re-run this every quarter. More than half of the registry's 42,230 entries had their current version published in the six weeks before we counted. Your developers' configs moved just as fast.

The one-line version

An MCP server reaches whatever the process that runs it can reach, and by default that is everything you can. The approval prompt manages the model; only the operating system manages the process. Put the boundary there — it is the one control in this whole stack that we measured at zero cost — and it stops mattering quite so much which of 41,713 servers your team installed last week. If you want someone to find the configs that quietly grant all of it, that is most of what the readiness audit does, and the same reasoning sits under the slopsquatting page: the fix for software you did not write is a permission boundary, not more trust.

Follow-up questions

Does the MCP client's approval prompt stop a server reading my files?
No. The prompt governs which tool calls the model is allowed to make. It has no say over what the server process does on its own once it is running — at startup, on a timer, or inside a tool you approved for something else. The specification itself tells clients to treat tool annotations as untrusted and to warn users that local servers run with the client's privileges. The only thing that limits the process is the operating system, so that is where the limit has to go.
Is a remote MCP server safer than a local one?
It is safer for your laptop and riskier for your data. A remote server cannot read your home directory, but everything you send it leaves your network, and it holds a token to whatever it fronts. A 2026 study of 7,973 live remote servers found 40.55% exposed tools with no authentication at all. Judge a remote server like a SaaS vendor — who runs it, what token it holds, what it logs — and a local one like a dependency that can run code.
The TypeScript SDK only passes a few environment variables. Doesn't that protect my secrets?
It protects secrets that live only in environment variables, which is fewer than people think. The SDK's default passes six variables on Linux and macOS, one of which is HOME — and your SSH keys, cloud credentials and package tokens live in files under HOME, not in the environment. Filtering the environment is good hygiene. It does not stop a process that can read your disk.
How do I sandbox an MCP server without breaking it?
Give it a filesystem view of only the folder it needs, no network unless its job is network access, and no home directory. On Linux that is a few unshare or bubblewrap flags; on any platform it can be a container with a bind mount and no network; VS Code has an opt-in sandbox setting on macOS and Linux. In our test the reference filesystem server ran all 14 tools identically inside a sandbox, with no measurable latency cost.
Should we pin MCP server versions?
Yes — by hash where the format allows it, by exact version everywhere else. A config that says npx with a bare package name runs whatever the package's latest release is at launch time. On npm, a third of registry entries already point at a version that is no longer the latest, and the first malicious MCP server in the wild turned bad in its sixteenth release, after fifteen clean ones. Pinning turns a silent update into a change someone reviews.

Sources

  1. Official MCP Registry API (v0), all servers, latest version of eachModel Context Protocol · 2026-10-12
  2. Security Best Practices (specification 2025-11-25)Model Context Protocol · 2025-11-25
  3. Tools (specification 2025-11-25)Model Context Protocol · 2025-11-25
  4. TypeScript SDK: stdio client transport and default inherited environmentmodelcontextprotocol/typescript-sdk on GitHub · 2026-10
  5. MCP Security Notification: Tool Poisoning AttacksBeurer-Kellner & Fischer, Invariant Labs · 2025-04-01
  6. Trust in MCP takes first in-the-wild hit via squatted Postmark connectorCSO Online · 2025-09-26
  7. SANDWORM_MODE: npm worm installs a rogue MCP server to steal developer secretsheise online, crediting Socket · 2026-02-26
  8. Shai-Hulud outbreak debrief: the worm evolves into MCPOX Security · 2026-08-09
  9. Critical RCE vulnerability in mcp-remote (CVE-2025-6514)JFrog Security Research · 2025-07-09
  10. Critical RCE vulnerability in Anthropic MCP Inspector (CVE-2025-49596)Oligo Security · 2025-06-27
  11. EscapeRoute: breaking the scope of Anthropic's Filesystem MCP server (CVE-2025-53109, CVE-2025-53110)Cymulate · 2025-07
  12. Add defense in depth against open firewalls, reverse proxies, and SSRF vulnerabilities with enhancements to the EC2 Instance Metadata ServiceAWS Security Blog · 2019-11-19
  13. MCP Servers: The New Security NightmareEquixly · 2025-03-29
  14. State of MCP Server Security 2025Astrix Security · 2025-10-15
  15. A First Measurement Study on Authentication Security in Real-World Remote MCP ServersZhou et al., arXiv:2605.22333 · 2026-05
  16. Breaking MCP server hosting: how a path traversal exposed 3,000+ serversGitGuardian · 2025-10-22
  17. Use MCP servers in VS Code (sandboxing and trust)Visual Studio Code documentation · 2026

Apply this to your own setup

The free readiness audit asks seven questions and returns a costed plan — the same reasoning as this page, against your numbers.

Disagree, or have a harder case?

Twenty minutes with the person who would build it. Bring the version of this problem that doesn't fit the page.