Skip to content

Commit 15b57d9

Browse files
committed
Update network permissions implementation docs
1 parent 49b7816 commit 15b57d9

File tree

3 files changed

+91
-23
lines changed

3 files changed

+91
-23
lines changed

docs/toolhive/guides-cli/custom-permissions.md

Lines changed: 76 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,6 @@ security and ensuring that MCP servers operate within defined boundaries.
1313
This guide shows you how to create and apply custom permission profiles for MCP
1414
servers, including built-in profiles and examples of common use cases.
1515

16-
:::important
17-
18-
Network access rules referenced in this document aren't currently implemented in
19-
ToolHive. They're a roadmap feature planned for future releases. For now, only
20-
file system permissions are enforced.
21-
22-
Contributions to help implement this feature are welcome! You can contribute by
23-
visiting our [GitHub repository](https://github.com/stacklok/toolhive).
24-
25-
:::
26-
2716
## Understanding permission profiles
2817

2918
Permissions are defined using JSON permission profiles. These profiles specify:
@@ -54,7 +43,9 @@ Profiles include the following sections:
5443
- `allow_transport`: List of allowed transport protocols (e.g., `tcp`,
5544
`udp`).
5645
- `allow_host`: List of allowed hostnames or IP addresses for outbound
57-
connections.
46+
connections. To allow all subdomains of a domain, prefix the domain with a
47+
period (e.g., `.github.com` allows any subdomain of `github.com`).
48+
Wildcards are not supported.
5849
- `allow_port`: List of allowed ports for outbound connections.
5950

6051
## Default permissions in the ToolHive registry
@@ -80,13 +71,13 @@ Permissions:
8071
- /tmp
8172
Network:
8273
Allow Transport: tcp
83-
Allow Host: google.com
74+
Allow Host: .google.com
8475
Allow Port: 443
8576
```
8677

8778
This example shows that the MCP server has read access to `/data`, read/write
88-
access to `/tmp`, and can make outbound TCP connections to `google.com` on
89-
port 443.
79+
access to `/tmp`, and can make outbound TCP connections to `*.google.com` (note
80+
the leading `.` which enables subdomain matching) on port 443.
9081

9182
Always verify the default permissions and override them with a custom profile if
9283
needed to meet your security policies.
@@ -134,7 +125,7 @@ For example:
134125
"outbound": {
135126
"insecure_allow_all": false,
136127
"allow_transport": ["tcp", "udp"],
137-
"allow_host": ["localhost", "google.com"],
128+
"allow_host": ["localhost", ".google.com"],
138129
"allow_port": [80, 443]
139130
}
140131
}
@@ -146,8 +137,8 @@ This profile:
146137
- Allows read-only access to `/example/path1` and `/example/path2`
147138
- Allows read and write access to `/example/path3` (note that the `write`
148139
setting also implies read access)
149-
- Allows outbound TCP or UDP connections to localhost and google.com on ports 80
150-
and 443
140+
- Allows outbound TCP or UDP connections to `localhost` and `google.com`
141+
(including subdomains) on ports 80 and 443
151142

152143
## Apply a permissions profile
153144

@@ -166,14 +157,79 @@ or
166157
thv run --permission-profile none <server-name>
167158
```
168159

160+
Add the `--isolate-network` flag to enforce network restrictions:
161+
162+
```bash
163+
thv run --isolate-network --permission-profile none <server-name>
164+
```
165+
169166
### Using a custom profile file
170167

171168
To run an MCP server with your custom profile:
172169

173170
```bash
174-
thv run --permission-profile </path/to/custom-profile.json> <server-name>
171+
thv run --isolate-network --permission-profile </path/to/custom-profile.json> <server-name>
175172
```
176173

174+
## Network isolation
175+
176+
To enforce the network access rules defined in your permission profile, you must
177+
use the `--isolate-network` flag when running the MCP server:
178+
179+
```bash
180+
thv run --isolate-network --permission-profile </path/to/custom-profile.json> <server-name>
181+
```
182+
183+
When network isolation is enabled, ToolHive creates a secure network
184+
architecture around your MCP server. Along with the main MCP server container,
185+
ToolHive launches:
186+
187+
- **Two Squid proxy containers** (ingress and egress) that filter incoming and
188+
outgoing network traffic
189+
- **A dnsmasq container** that provides controlled DNS resolution
190+
191+
This multi-container setup ensures that all network traffic flows through
192+
controlled proxy points, allowing ToolHive to enforce the network access rules
193+
specified in your permission profile.
194+
195+
```mermaid
196+
graph TB
197+
subgraph "Host network"
198+
Client[MCP client]
199+
THVProxy[ToolHive SSE proxy]
200+
end
201+
202+
subgraph "Docker networks"
203+
subgraph "toolhive-external"
204+
IngressProxy["Ingress proxy<br>(squid)"]
205+
end
206+
207+
subgraph "toolhive-{name}-internal"
208+
MCPServer[MCP server<br>container]
209+
EgressProxy["Egress proxy<br>(squid)"]
210+
DNSContainer["DNS container<br/>(dnsmasq)"]
211+
end
212+
end
213+
214+
External[External resources]
215+
216+
%% Traffic Flow
217+
Client -->|SSE/HTTP request| THVProxy
218+
THVProxy -->|Forward| IngressProxy
219+
IngressProxy -->|Reverse proxy| MCPServer
220+
MCPServer -->|Outbound requests| EgressProxy
221+
EgressProxy -->|Filtered traffic| External
222+
MCPServer -.->|DNS queries| DNSContainer
223+
```
224+
225+
:::note
226+
227+
Network isolation currently supports only HTTP and HTTPS protocols. Other
228+
protocols like TCP sockets for database connections will not work with network
229+
isolation enabled.
230+
231+
:::
232+
177233
## Example: Restrict network access
178234

179235
The GitHub MCP server in the registry has a default profile that allows access
@@ -198,7 +254,7 @@ Enterprise instance:
198254
2. Run the GitHub MCP server with this profile:
199255

200256
```bash
201-
thv run --permission-profile ./github-profile.json --secret github,target=GITHUB_PERSONAL_ACCESS_TOKEN github
257+
thv run --isolate-network --permission-profile ./github-profile.json --secret github,target=GITHUB_PERSONAL_ACCESS_TOKEN github
202258
```
203259

204260
This restricts the GitHub MCP server to make HTTPS connections only to

docs/toolhive/guides-k8s/run-mcp-k8s.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,17 @@ Permission profiles can be configured in two ways:
414414
The ConfigMap should contain a JSON
415415
[permissions profile](../guides-cli/custom-permissions.md#create-a-custom-permissions-profile).
416416

417+
:::important
418+
419+
Outbound network filtering using permission profiles isn't currently implemented
420+
in the ToolHive Operator. This is a roadmap feature planned for future releases.
421+
For now, only file system permissions are enforced.
422+
423+
Contributions to help implement this feature are welcome! You can contribute by
424+
visiting our [GitHub repository](https://github.com/stacklok/toolhive).
425+
426+
:::
427+
417428
## Next steps
418429

419430
See the [Client compatibility](../reference/client-compatibility.mdx) reference

docs/toolhive/index.mdx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,10 @@ ToolHive offers the following features to simplify MCP deployment:
9797
servers that you can discover and run effortlessly.
9898

9999
- **Comprehensive security**: Run MCP servers in isolated containers with
100-
customizable, fine-grained permissions using JSON profiles. Securely manage
101-
secrets and configurations using built-in encrypted storage or 1Password
102-
integration, eliminating plaintext secrets in configuration files.
100+
customizable, fine-grained permissions and network access filtering using JSON
101+
profiles. Securely manage secrets and configurations using built-in encrypted
102+
storage or 1Password integration, eliminating plaintext secrets in
103+
configuration files.
103104

104105
- **Enterprise readiness**: Implement robust OAuth-based authorization controls
105106
for enterprise environments that integrate seamlessly with existing

0 commit comments

Comments
 (0)