One read of Model Context Protocolmcp-20261005T203716Z
2 pages moved out of 351 read.
What this read moved
1-2 of 2docs/2026-07-28/tutorials/security/local-server-security New page · 439 lines, new page
# Local Server Security ## What a Local Server Can Touch ### The stdio Trust Model ### Threats This Guide Addresses ## Ask Whether It Needs to Run Locally ## Check Provenance Before You Install ## Treat Tool Definitions as Untrusted Input ## Run Servers in an Isolated Environment ## Isolate Credentials ## Limit Filesystem Access ## Control Network Egress ## Managing Local Servers Across an Organization ## Checklist ## Next Steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Local Server Security
> Practical defaults for running MCP servers safely on your own machine.
Most MCP security documentation covers the protocol threat model: OAuth flows,
token handling, session hijacking, and confused deputy attacks. For those, see
[Authorization](/docs/2026-07-28/tutorials/security/authorization) and
[Security Best Practices](/docs/2026-07-28/tutorials/security/security_best_practices).
This guide covers a different threat model: **your machine**. When you run an
MCP server locally, you download code from the internet and run it as a child
process of your user account. That process inherits your environment
variables, can read anything your account can read — SSH keys, cloud
credentials, browser profiles, your home directory — and can open outbound
network connections to anywhere. None of that is governed by the protocol.
It is governed by how you run the process.
<Note>
**Scope**: this guide is about servers running on a machine you (or your
organization's users) control — a laptop or workstation, typically launched
over stdio. Deploying and hardening remote or hosted servers is a different
topic with different controls.
</Note>
<Tip>
**If you do one thing after reading this**: open your client's MCP
configuration, remove the servers you no longer use, and make sure you know
where each remaining one comes from and that its version is pinned. Everything
else in this guide builds on knowing what you are actually running.
</Tip>
## What a Local Server Can Touch
A local MCP server is not a plugin running inside a sandbox the protocol
provides. It is an ordinary operating system process, launched by your host
application, with all the access that implies:
```mermaid theme={null}
flowchart LR
Host["Host application<br/>(MCP client)"] -->|launches| Server["Local MCP server<br/>(ordinary child process)"]
Server --> Env["Environment variables<br/>(tokens, API keys)"]
Server --> FS["Files your account<br/>can read and write"]
Server --> Net["Unrestricted outbound<br/>network access"]
Server --> Deps["Its full dependency tree,<br/>fetched at install time"]
```
Clients that offer one-click installation are required to show you the exact
command before it runs
([SEP-1024](/seps/1024-mcp-client-security-requirements-for-local-server-)),
but a consent dialog only helps if you know what to look for. That is what
the rest of this guide is about.
### The stdio Trust Model
Most local servers use the stdio transport: your client spawns the server as
a subprocess, and the two communicate over stdin and stdout. That design
carries an important assumption: **the client and a stdio server share one
trust domain.** They run side by side with the same privileges, and neither
the protocol nor the SDKs defend one against the other — a server already
has code execution on your machine by virtue of being launched, so there is
no boundary between the two processes for a transport to enforce. This is by
design: the SDKs assume full trust between stdio peers, and any isolation or
security fencing around a local server is the responsibility of the host
application and of whoever operates the machine.
Two practical consequences:
* Your real security decisions happen **before launch**: what you install
(provenance) and how you run it (isolation). The stdio transport is not a
sandbox.
* If you run a server at reduced privilege, that boundary is yours to
enforce — a container, sandbox, or VM, as described below.
The trust domain is also cumulative. Every server you configure shares the
same model context, so a malicious server can influence how the agent uses
the tools of every other server. Each install extends the surface all the
others are exposed to.
### Threats This Guide Addresses
1. **A malicious server.** Typosquatted package names, lookalike
repositories, or an abandoned project taken over by a new publisher. The
"server" works as advertised while also exfiltrating your environment or
files.
2. **An overcollecting server.** A legitimate server that collects more than
its job requires: environment variables, files, or network traffic it has
no reason to touch. Prompt injection in untrusted content can steer an
honest server into the same overreach, using whatever access it was
given.
3. **A compromised dependency.** The server author is honest, but one of the
packages in its dependency tree was compromised in a supply chain attack.
4. **A poisoned tool catalog.** Tool names and descriptions are instructions
your model reads. A server can hide directives in them that steer the
agent — including how it uses *other* servers' tools — without the
poisoned tool ever being invoked (often called tool poisoning, or tool
shadowing when it targets another server's tools). Definitions are not
fixed at install time either: a server can quietly change them after you
approved it (a rug pull), so a one-time consent dialog and package
pinning do not cover this surface.
5. **A vulnerable server or bridge.** A legitimate, unmodified component can
still be the way in. Local bridges that connect stdio clients to remote
servers have had critical flaws triggered by nothing more than connecting
to a malicious endpoint, and local developer tools listening on a port
have been exploited directly from a web page.
Out of scope: attackers with physical access to your machine, targeted
nation-state attacks, and protocol-level attacks (see the linked documents
above).
Before the mitigations, one fact that shapes them all: **no check proves
what a server will do.** The protocol cannot guarantee that a server is
what it claims or does only what it promises. Provenance signals — a
readable repository, signatures, an SBOM, a curated listing — tell you who
you are trusting, not that the trust is warranted, and short of auditing
and building every release yourself, you cannot verify behavior in advance.
The mitigations below therefore follow one principle: **treat a third-party
local server as untrusted code with exactly the privileges you hand it —
and hand it as few as possible.** Vetting reduces the odds of a bad trust
decision; containment decides what a bad one costs. Each section gives a
baseline, an optional "going further" step, and a default if you are
unsure.
## Ask Whether It Needs to Run Locally
The cheapest way to shrink a blast radius is not to create one. Before you
install a server as a local process, ask what it actually needs from your
machine. Reading your working tree, driving a local tool, or reaching
hardware are reasons to run locally. Wrapping a remote API is not: a server
that only talks to a service on the internet gains nothing from running on
your laptop, while you take on everything else in this guide for no benefit.
* **Prefer the remote version where one exists.** A server offered over
[Streamable HTTP](/specification/2026-07-28/basic/transports/streamable-http)
runs no code on your machine, uses the protocol's authorization flow
instead of a token in a local config file, and is patched in one place.
The protocol threat model (linked above) applies to it instead of this
one.
* **Treat an unnecessary local install as a signal.** When a third-party
server needs no local access yet ships only as a stdio process, ask why.
It may just be the author's path of least resistance, but it is also
exactly how a malicious or overcollecting server gets onto your machine.
* **Keep the genuine exceptions.** Some capabilities only exist as a local
process. For those, the rest of this guide applies in full.
**If unsure**: when a server needs none of your files, local tools, or local
network, use its remote version and skip the local install entirely.
## Check Provenance Before You Install
A listing on a registry is not an endorsement. Docker Hub, ghcr.io, npm,
PyPI, and NuGet will host almost anything, and a package being popular or
well-named guarantees neither that it is safe nor that it is current. Even
curated MCP catalogs describe their own vetting as best-effort: curation
reduces risk, it does not take on accountability for what you run.
Before installing a server:
* **Identify the publisher.** Can you tie the package to a source repository
and a real maintainer or organization? Does the repository show recent,
plausible activity?
* **Verify the exact package name.** Typosquatting is the cheapest attack
available. Confirm you are installing the package the documentation
actually refers to, not a lookalike.
* **Pin the version.** Install a specific version rather than `latest`, so
a compromised future release does not walk onto your machine through an
auto-update. Pair the pin with a deliberate update habit: when a security
advisory lands for something you pinned, the pin is what keeps you
vulnerable.
* **Know what the pin covers.** Pinning a package version with a launcher
such as `npx` or `uvx` fixes only the top-level package; its transitive
dependencies are typically resolved fresh at install time, which is
exactly where a compromised dependency arrives. Pinning a container image
by digest (`image@sha256:...`) freezes the entire dependency tree.
* **Prefer artifacts with provenance metadata.** Signed artifacts, build
attestations, and SBOMs (software bills of materials) let you verify who
built the artifact and what is inside it — including which MCP SDK and
version it uses, which matters when a vulnerability is announced in one.
**Going further**: verify signatures and attestations rather than just
noting their presence (for example with Sigstore tooling or your registry's
attestation verification), and generate your own SBOM from the artifact (for
example with Syft or Trivy) instead of trusting the published one. Some
registries and runtimes can verify signatures at launch time rather than
only at install, turning provenance from a one-time check into a standing
one.
**If unsure**: only install servers whose source code you can read and whose
publisher you can identify, and pin the exact version.
## Treat Tool Definitions as Untrusted Input
Installing a server is not the last trust decision. At runtime, the server
sends your client its tool names and descriptions, and the model reads them
as instructions — an injection surface that install-time review does not
cover.
* **Read the tool list before you rely on a server.** Most clients can show
each tool's description, and the
[MCP Inspector](/docs/2026-07-28/tools/inspector) lists every tool a
server exposes without a model in the loop. If a description contains
instructions that have nothing to do with the tool's job, remove the
server.
* **Prefer clients that pin tool definitions.** Some clients record tool
definitions when you first approve a server and ask again when they
change. The protocol does not require this, so it is a property worth
choosing a client for.
* **Keep the roster small.** Because all configured servers share the
model's context, every server you add extends the surface the others are
exposed to.
**If unsure**: install a few servers, skim their tool descriptions once, and
favor a client that re-prompts when a tool definition changes.
## Run Servers in an Isolated Environment
Process isolation is the single highest-leverage mitigation in this guide.
It turns "this server can read my SSH keys" into "this server can read an
empty directory", and it protects you even when provenance checks fail —
against all the threats above at once.
* **Baseline**: run third-party servers inside a container (for example with
Docker or Podman) with no volume mounts beyond what the server needs.
Stdio transport works unchanged: the client talks to the container's stdin
and stdout exactly as it would to a bare process.
* **Alternatives**: a lightweight virtual machine dedicated to development
work, or your operating system's process-sandboxing facilities. Some
MCP-focused runtimes and client integrations will wrap servers in
containers for you; the pattern matters more than the tool.
A container is not an impenetrable boundary, but it removes the default
access to your environment, your files, and your keychain — which is what
the common attacks rely on.
**Going further**: harden the container itself — a seccomp profile limits
the system calls it can make, and a Linux security module such as AppArmor
or SELinux limits what it can reach, often by doing no more than enabling
your distribution's defaults. Beyond that, run servers under a microVM or in
a separate user account, and combine isolation with the network controls
below so the sandbox also cannot exfiltrate what little it can see.
**If unsure**: run every third-party server in a container with nothing
mounted except the directory it is meant to work on.
## Isolate Credentials
A locally launched server may inherit the environment of whatever launched
it. If your shell profile exports cloud credentials and API tokens globally,
every server you run can potentially read all of them.
* **Pass secrets per server, not globally.** Use the per-server environment
configuration in your client's config file rather than exporting secrets
in your shell profile, so each server sees only its own credentials.
* **Scope tokens narrowly.** Issue each server its own token with the
smallest scope that works (for example a fine-grained access token limited
to one repository, not your account-wide token), so a leak is contained
and revocable.
* **Keep long-lived secrets out of plaintext config.** Client configuration
files are a known, predictable location on disk. Prefer your operating
system's secret store (such as macOS Keychain, Windows Credential Manager,
or the freedesktop Secret Service on Linux) where your client supports
referencing it.
* **Remember files count too.** `~/.ssh`, `~/.aws`, and similar directories
are credentials on disk. Process isolation (above) is what actually keeps
them out of a server's reach.
**Going further**: use short-lived credentials issued at launch time by a
secrets manager or broker instead of static tokens, and rotate anything a
server held if you decide to remove that server.
**If unsure**: give each server its own narrowly scoped token via its
per-server config, and never reuse a personal broad-scope token across
servers.
## Limit Filesystem Access
Many useful servers legitimately need file access. The question is how much.
* **Grant the narrowest root that works.** Configure filesystem-oriented
servers with a specific project directory, passed explicitly through the
server's configuration or tool parameters — never your home directory.
* **Prefer read-only.** If the server's job is to read code or documents,
mount or grant the directory read-only.
* **Be suspicious of breadth.** A server that asks for a broad root
directory to do a narrow job is overreaching. Grant a narrower directory,
or pick a different server.
<Warning>
Configuration-level allowlists are **cooperative boundaries**: a well-behaved
server respects them, but nothing in the protocol stops a malicious or
compromised one from reading whatever the process can reach. Treat them as
guardrails for honest servers. Enforcement comes from the isolation layer
above — a sandbox or container where the allowed directory is the only
filesystem that exists.
</Warning>
**Going further**: combine allowlists with isolation, so the only filesystem
the server can even see is the mount you chose.
**If unsure**: grant access to a single project directory, read-only.
Cut at 300 lines. The page has the rest.
docs/draft/tutorials/security/local-server-security New page · 439 lines, new page
# Local Server Security ## What a Local Server Can Touch ### The stdio Trust Model ### Threats This Guide Addresses ## Ask Whether It Needs to Run Locally ## Check Provenance Before You Install ## Treat Tool Definitions as Untrusted Input ## Run Servers in an Isolated Environment ## Isolate Credentials ## Limit Filesystem Access ## Control Network Egress ## Managing Local Servers Across an Organization ## Checklist ## Next Steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Local Server Security
> Practical defaults for running MCP servers safely on your own machine.
Most MCP security documentation covers the protocol threat model: OAuth flows,
token handling, session hijacking, and confused deputy attacks. For those, see
[Authorization](/docs/draft/tutorials/security/authorization) and
[Security Best Practices](/docs/draft/tutorials/security/security_best_practices).
This guide covers a different threat model: **your machine**. When you run an
MCP server locally, you download code from the internet and run it as a child
process of your user account. That process inherits your environment
variables, can read anything your account can read — SSH keys, cloud
credentials, browser profiles, your home directory — and can open outbound
network connections to anywhere. None of that is governed by the protocol.
It is governed by how you run the process.
<Note>
**Scope**: this guide is about servers running on a machine you (or your
organization's users) control — a laptop or workstation, typically launched
over stdio. Deploying and hardening remote or hosted servers is a different
topic with different controls.
</Note>
<Tip>
**If you do one thing after reading this**: open your client's MCP
configuration, remove the servers you no longer use, and make sure you know
where each remaining one comes from and that its version is pinned. Everything
else in this guide builds on knowing what you are actually running.
</Tip>
## What a Local Server Can Touch
A local MCP server is not a plugin running inside a sandbox the protocol
provides. It is an ordinary operating system process, launched by your host
application, with all the access that implies:
```mermaid theme={null}
flowchart LR
Host["Host application<br/>(MCP client)"] -->|launches| Server["Local MCP server<br/>(ordinary child process)"]
Server --> Env["Environment variables<br/>(tokens, API keys)"]
Server --> FS["Files your account<br/>can read and write"]
Server --> Net["Unrestricted outbound<br/>network access"]
Server --> Deps["Its full dependency tree,<br/>fetched at install time"]
```
Clients that offer one-click installation are required to show you the exact
command before it runs
([SEP-1024](/seps/1024-mcp-client-security-requirements-for-local-server-)),
but a consent dialog only helps if you know what to look for. That is what
the rest of this guide is about.
### The stdio Trust Model
Most local servers use the stdio transport: your client spawns the server as
a subprocess, and the two communicate over stdin and stdout. That design
carries an important assumption: **the client and a stdio server share one
trust domain.** They run side by side with the same privileges, and neither
the protocol nor the SDKs defend one against the other — a server already
has code execution on your machine by virtue of being launched, so there is
no boundary between the two processes for a transport to enforce. This is by
design: the SDKs assume full trust between stdio peers, and any isolation or
security fencing around a local server is the responsibility of the host
application and of whoever operates the machine.
Two practical consequences:
* Your real security decisions happen **before launch**: what you install
(provenance) and how you run it (isolation). The stdio transport is not a
sandbox.
* If you run a server at reduced privilege, that boundary is yours to
enforce — a container, sandbox, or VM, as described below.
The trust domain is also cumulative. Every server you configure shares the
same model context, so a malicious server can influence how the agent uses
the tools of every other server. Each install extends the surface all the
others are exposed to.
### Threats This Guide Addresses
1. **A malicious server.** Typosquatted package names, lookalike
repositories, or an abandoned project taken over by a new publisher. The
"server" works as advertised while also exfiltrating your environment or
files.
2. **An overcollecting server.** A legitimate server that collects more than
its job requires: environment variables, files, or network traffic it has
no reason to touch. Prompt injection in untrusted content can steer an
honest server into the same overreach, using whatever access it was
given.
3. **A compromised dependency.** The server author is honest, but one of the
packages in its dependency tree was compromised in a supply chain attack.
4. **A poisoned tool catalog.** Tool names and descriptions are instructions
your model reads. A server can hide directives in them that steer the
agent — including how it uses *other* servers' tools — without the
poisoned tool ever being invoked (often called tool poisoning, or tool
shadowing when it targets another server's tools). Definitions are not
fixed at install time either: a server can quietly change them after you
approved it (a rug pull), so a one-time consent dialog and package
pinning do not cover this surface.
5. **A vulnerable server or bridge.** A legitimate, unmodified component can
still be the way in. Local bridges that connect stdio clients to remote
servers have had critical flaws triggered by nothing more than connecting
to a malicious endpoint, and local developer tools listening on a port
have been exploited directly from a web page.
Out of scope: attackers with physical access to your machine, targeted
nation-state attacks, and protocol-level attacks (see the linked documents
above).
Before the mitigations, one fact that shapes them all: **no check proves
what a server will do.** The protocol cannot guarantee that a server is
what it claims or does only what it promises. Provenance signals — a
readable repository, signatures, an SBOM, a curated listing — tell you who
you are trusting, not that the trust is warranted, and short of auditing
and building every release yourself, you cannot verify behavior in advance.
The mitigations below therefore follow one principle: **treat a third-party
local server as untrusted code with exactly the privileges you hand it —
and hand it as few as possible.** Vetting reduces the odds of a bad trust
decision; containment decides what a bad one costs. Each section gives a
baseline, an optional "going further" step, and a default if you are
unsure.
## Ask Whether It Needs to Run Locally
The cheapest way to shrink a blast radius is not to create one. Before you
install a server as a local process, ask what it actually needs from your
machine. Reading your working tree, driving a local tool, or reaching
hardware are reasons to run locally. Wrapping a remote API is not: a server
that only talks to a service on the internet gains nothing from running on
your laptop, while you take on everything else in this guide for no benefit.
* **Prefer the remote version where one exists.** A server offered over
[Streamable HTTP](/specification/draft/basic/transports/streamable-http)
runs no code on your machine, uses the protocol's authorization flow
instead of a token in a local config file, and is patched in one place.
The protocol threat model (linked above) applies to it instead of this
one.
* **Treat an unnecessary local install as a signal.** When a third-party
server needs no local access yet ships only as a stdio process, ask why.
It may just be the author's path of least resistance, but it is also
exactly how a malicious or overcollecting server gets onto your machine.
* **Keep the genuine exceptions.** Some capabilities only exist as a local
process. For those, the rest of this guide applies in full.
**If unsure**: when a server needs none of your files, local tools, or local
network, use its remote version and skip the local install entirely.
## Check Provenance Before You Install
A listing on a registry is not an endorsement. Docker Hub, ghcr.io, npm,
PyPI, and NuGet will host almost anything, and a package being popular or
well-named guarantees neither that it is safe nor that it is current. Even
curated MCP catalogs describe their own vetting as best-effort: curation
reduces risk, it does not take on accountability for what you run.
Before installing a server:
* **Identify the publisher.** Can you tie the package to a source repository
and a real maintainer or organization? Does the repository show recent,
plausible activity?
* **Verify the exact package name.** Typosquatting is the cheapest attack
available. Confirm you are installing the package the documentation
actually refers to, not a lookalike.
* **Pin the version.** Install a specific version rather than `latest`, so
a compromised future release does not walk onto your machine through an
auto-update. Pair the pin with a deliberate update habit: when a security
advisory lands for something you pinned, the pin is what keeps you
vulnerable.
* **Know what the pin covers.** Pinning a package version with a launcher
such as `npx` or `uvx` fixes only the top-level package; its transitive
dependencies are typically resolved fresh at install time, which is
exactly where a compromised dependency arrives. Pinning a container image
by digest (`image@sha256:...`) freezes the entire dependency tree.
* **Prefer artifacts with provenance metadata.** Signed artifacts, build
attestations, and SBOMs (software bills of materials) let you verify who
built the artifact and what is inside it — including which MCP SDK and
version it uses, which matters when a vulnerability is announced in one.
**Going further**: verify signatures and attestations rather than just
noting their presence (for example with Sigstore tooling or your registry's
attestation verification), and generate your own SBOM from the artifact (for
example with Syft or Trivy) instead of trusting the published one. Some
registries and runtimes can verify signatures at launch time rather than
only at install, turning provenance from a one-time check into a standing
one.
**If unsure**: only install servers whose source code you can read and whose
publisher you can identify, and pin the exact version.
## Treat Tool Definitions as Untrusted Input
Installing a server is not the last trust decision. At runtime, the server
sends your client its tool names and descriptions, and the model reads them
as instructions — an injection surface that install-time review does not
cover.
* **Read the tool list before you rely on a server.** Most clients can show
each tool's description, and the
[MCP Inspector](/docs/draft/tools/inspector) lists every tool a
server exposes without a model in the loop. If a description contains
instructions that have nothing to do with the tool's job, remove the
server.
* **Prefer clients that pin tool definitions.** Some clients record tool
definitions when you first approve a server and ask again when they
change. The protocol does not require this, so it is a property worth
choosing a client for.
* **Keep the roster small.** Because all configured servers share the
model's context, every server you add extends the surface the others are
exposed to.
**If unsure**: install a few servers, skim their tool descriptions once, and
favor a client that re-prompts when a tool definition changes.
## Run Servers in an Isolated Environment
Process isolation is the single highest-leverage mitigation in this guide.
It turns "this server can read my SSH keys" into "this server can read an
empty directory", and it protects you even when provenance checks fail —
against all the threats above at once.
* **Baseline**: run third-party servers inside a container (for example with
Docker or Podman) with no volume mounts beyond what the server needs.
Stdio transport works unchanged: the client talks to the container's stdin
and stdout exactly as it would to a bare process.
* **Alternatives**: a lightweight virtual machine dedicated to development
work, or your operating system's process-sandboxing facilities. Some
MCP-focused runtimes and client integrations will wrap servers in
containers for you; the pattern matters more than the tool.
A container is not an impenetrable boundary, but it removes the default
access to your environment, your files, and your keychain — which is what
the common attacks rely on.
**Going further**: harden the container itself — a seccomp profile limits
the system calls it can make, and a Linux security module such as AppArmor
or SELinux limits what it can reach, often by doing no more than enabling
your distribution's defaults. Beyond that, run servers under a microVM or in
a separate user account, and combine isolation with the network controls
below so the sandbox also cannot exfiltrate what little it can see.
**If unsure**: run every third-party server in a container with nothing
mounted except the directory it is meant to work on.
## Isolate Credentials
A locally launched server may inherit the environment of whatever launched
it. If your shell profile exports cloud credentials and API tokens globally,
every server you run can potentially read all of them.
* **Pass secrets per server, not globally.** Use the per-server environment
configuration in your client's config file rather than exporting secrets
in your shell profile, so each server sees only its own credentials.
* **Scope tokens narrowly.** Issue each server its own token with the
smallest scope that works (for example a fine-grained access token limited
to one repository, not your account-wide token), so a leak is contained
and revocable.
* **Keep long-lived secrets out of plaintext config.** Client configuration
files are a known, predictable location on disk. Prefer your operating
system's secret store (such as macOS Keychain, Windows Credential Manager,
or the freedesktop Secret Service on Linux) where your client supports
referencing it.
* **Remember files count too.** `~/.ssh`, `~/.aws`, and similar directories
are credentials on disk. Process isolation (above) is what actually keeps
them out of a server's reach.
**Going further**: use short-lived credentials issued at launch time by a
secrets manager or broker instead of static tokens, and rotate anything a
server held if you decide to remove that server.
**If unsure**: give each server its own narrowly scoped token via its
per-server config, and never reuse a personal broad-scope token across
servers.
## Limit Filesystem Access
Many useful servers legitimately need file access. The question is how much.
* **Grant the narrowest root that works.** Configure filesystem-oriented
servers with a specific project directory, passed explicitly through the
server's configuration or tool parameters — never your home directory.
* **Prefer read-only.** If the server's job is to read code or documents,
mount or grant the directory read-only.
* **Be suspicious of breadth.** A server that asks for a broad root
directory to do a narrow job is overreaching. Grant a narrower directory,
or pick a different server.
<Warning>
Configuration-level allowlists are **cooperative boundaries**: a well-behaved
server respects them, but nothing in the protocol stops a malicious or
compromised one from reading whatever the process can reach. Treat them as
guardrails for honest servers. Enforcement comes from the isolation layer
above — a sandbox or container where the allowed directory is the only
filesystem that exists.
</Warning>
**Going further**: combine allowlists with isolation, so the only filesystem
the server can even see is the mount you chose.
**If unsure**: grant access to a single project directory, read-only.
Cut at 300 lines. The page has the rest.