@@ -13,17 +13,6 @@ security and ensuring that MCP servers operate within defined boundaries.
1313This guide shows you how to create and apply custom permission profiles for MCP
1414servers, 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
2918Permissions 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
8778This 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
9182Always verify the default permissions and override them with a custom profile if
9283needed 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
166157thv 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
171168To 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
179235The GitHub MCP server in the registry has a default profile that allows access
@@ -198,7 +254,7 @@ Enterprise instance:
1982542 . 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
204260This restricts the GitHub MCP server to make HTTPS connections only to
0 commit comments