mcpshield-runtime 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mcpshield_runtime-0.1.0/PKG-INFO +279 -0
- mcpshield_runtime-0.1.0/README.md +254 -0
- mcpshield_runtime-0.1.0/mcpshield_runtime.egg-info/PKG-INFO +279 -0
- mcpshield_runtime-0.1.0/mcpshield_runtime.egg-info/SOURCES.txt +21 -0
- mcpshield_runtime-0.1.0/mcpshield_runtime.egg-info/dependency_links.txt +1 -0
- mcpshield_runtime-0.1.0/mcpshield_runtime.egg-info/entry_points.txt +2 -0
- mcpshield_runtime-0.1.0/mcpshield_runtime.egg-info/requires.txt +9 -0
- mcpshield_runtime-0.1.0/mcpshield_runtime.egg-info/top_level.txt +1 -0
- mcpshield_runtime-0.1.0/pyproject.toml +46 -0
- mcpshield_runtime-0.1.0/runtime/__init__.py +0 -0
- mcpshield_runtime-0.1.0/runtime/api/__init__.py +0 -0
- mcpshield_runtime-0.1.0/runtime/api/main.py +73 -0
- mcpshield_runtime-0.1.0/runtime/audit_logger.py +67 -0
- mcpshield_runtime-0.1.0/runtime/cli.py +149 -0
- mcpshield_runtime-0.1.0/runtime/models.py +27 -0
- mcpshield_runtime-0.1.0/runtime/policy_engine.py +56 -0
- mcpshield_runtime-0.1.0/runtime/risk_scorer.py +30 -0
- mcpshield_runtime-0.1.0/runtime/sandbox/__init__.py +0 -0
- mcpshield_runtime-0.1.0/runtime/sandbox/base.py +15 -0
- mcpshield_runtime-0.1.0/runtime/sandbox/docker_backend.py +43 -0
- mcpshield_runtime-0.1.0/runtime/static/dashboard.html +151 -0
- mcpshield_runtime-0.1.0/setup.cfg +4 -0
- mcpshield_runtime-0.1.0/tests/test_policy_engine.py +55 -0
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mcpshield-runtime
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Secure MCP runtime — policy enforcement, SSRF blocking, audit logging
|
|
5
|
+
Author: Sri Sowmya Nemani
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/srisowmya2000/mcp-shield
|
|
8
|
+
Project-URL: Repository, https://github.com/srisowmya2000/mcp-shield
|
|
9
|
+
Keywords: mcp,security,ssrf,llm,agent,policy,sandbox
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Topic :: Security
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Requires-Python: >=3.12
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
Requires-Dist: fastapi>=0.115
|
|
17
|
+
Requires-Dist: uvicorn>=0.30
|
|
18
|
+
Requires-Dist: pydantic>=2.0
|
|
19
|
+
Requires-Dist: pydantic-settings>=2.0
|
|
20
|
+
Requires-Dist: typer>=0.12
|
|
21
|
+
Requires-Dist: mcp>=1.0
|
|
22
|
+
Requires-Dist: httpx>=0.27
|
|
23
|
+
Requires-Dist: pyyaml>=6.0
|
|
24
|
+
Requires-Dist: rich>=13.0
|
|
25
|
+
|
|
26
|
+
# mcp-shield 🛡️
|
|
27
|
+
|
|
28
|
+
> **The security runtime for MCP servers.**
|
|
29
|
+
> Every tool call inspected. Every attack blocked. Every decision logged.
|
|
30
|
+
|
|
31
|
+

|
|
32
|
+

|
|
33
|
+

|
|
34
|
+

|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## What is MCP?
|
|
39
|
+
|
|
40
|
+
**Model Context Protocol (MCP)** is an open standard that lets AI assistants (like Claude, Cursor, Copilot) connect to external tools and services — file systems, APIs, databases, browsers — through **MCP servers**.
|
|
41
|
+
|
|
42
|
+
Think of MCP servers as plugins that give AI agents real-world capabilities.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## The Problem
|
|
47
|
+
|
|
48
|
+
MCP servers run as **trusted processes** on your machine with access to:
|
|
49
|
+
|
|
50
|
+
| Access | Risk |
|
|
51
|
+
|---|---|
|
|
52
|
+
| 🗂️ Your filesystem | Read `/etc/passwd`, steal SSH keys |
|
|
53
|
+
| 🌐 Your network | SSRF to `169.254.169.254` (AWS metadata) |
|
|
54
|
+
| 🔑 Your environment variables | Steal API keys, tokens, secrets |
|
|
55
|
+
| ⚙️ Shell execution | Run arbitrary commands |
|
|
56
|
+
|
|
57
|
+
**A malicious or compromised MCP server can silently exfiltrate your secrets, pivot to internal infrastructure, or execute code — and you'd never know.**
|
|
58
|
+
|
|
59
|
+
This is not theoretical. A real SSRF vulnerability was found in an MCP OAuth HTTP transport implementation that allowed exactly this class of attack.
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## How mcp-shield Fixes This
|
|
64
|
+
|
|
65
|
+
mcp-shield sits **between your AI agent and the MCP server** as a policy enforcement layer.
|
|
66
|
+
Before any tool executes, mcp-shield evaluates it. If it's not allowed — it's blocked.
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
AI Agent
|
|
70
|
+
│
|
|
71
|
+
▼
|
|
72
|
+
mcp-shield /inspect
|
|
73
|
+
│
|
|
74
|
+
├── Tool allowlist check → "read_secrets" not allowed → 🚫 BLOCK
|
|
75
|
+
├── Blocked pattern check → "ssrf_fetch" is dangerous → 🚫 BLOCK
|
|
76
|
+
├── Argument scanning → "169.254.169.254" in args → 🚫 BLOCK
|
|
77
|
+
│
|
|
78
|
+
└── Passed all checks → ✅ ALLOW → MCP Server executes
|
|
79
|
+
│
|
|
80
|
+
▼
|
|
81
|
+
Audit Log (SQLite)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Every decision — ALLOW or BLOCK — is logged with a full audit trail.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Live Demo
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
# Start mcp-shield
|
|
92
|
+
uvicorn runtime.api.main:app --reload
|
|
93
|
+
|
|
94
|
+
# 🚫 Attempt secret theft → BLOCKED
|
|
95
|
+
curl -X POST http://localhost:8000/inspect \
|
|
96
|
+
-H "Content-Type: application/json" \
|
|
97
|
+
-d '{"server_name":"evil","policy":"default","tool_call":{"tool_name":"read_secrets","arguments":{}}}'
|
|
98
|
+
|
|
99
|
+
# → {"decision":"BLOCK","reason":"Tool 'read_secrets' is not in the allowed_tools list","blocked":true}
|
|
100
|
+
|
|
101
|
+
# 🚫 Attempt SSRF to AWS metadata endpoint → BLOCKED
|
|
102
|
+
curl -X POST http://localhost:8000/inspect \
|
|
103
|
+
-H "Content-Type: application/json" \
|
|
104
|
+
-d '{"server_name":"evil","policy":"default","tool_call":{"tool_name":"ssrf_fetch","arguments":{"url":"http://169.254.169.254/latest/meta-data/"}}}'
|
|
105
|
+
|
|
106
|
+
# → {"decision":"BLOCK","reason":"Argument contains blocked pattern: '169.254.169.254'","blocked":true}
|
|
107
|
+
|
|
108
|
+
# ✅ Safe tool → ALLOWED
|
|
109
|
+
curl -X POST http://localhost:8000/inspect \
|
|
110
|
+
-H "Content-Type: application/json" \
|
|
111
|
+
-d '{"server_name":"safe","policy":"default","tool_call":{"tool_name":"safe_tool","arguments":{"name":"Sri"}}}'
|
|
112
|
+
|
|
113
|
+
# → {"decision":"ALLOW","reason":"Passed all policy checks","blocked":false}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## Key Features
|
|
119
|
+
|
|
120
|
+
| Feature | Description |
|
|
121
|
+
|---|---|
|
|
122
|
+
| 🔒 **Policy Engine** | YAML-based allowlists + blocked patterns, per-server policies |
|
|
123
|
+
| 🔍 **Argument Scanning** | Recursively scans nested args for SSRF, path traversal, dangerous patterns |
|
|
124
|
+
| 📋 **Audit Logger** | Every decision logged to SQLite with timestamp, server, tool, reason |
|
|
125
|
+
| 🐳 **Docker Sandbox** | Hardened containers: `--cap-drop=ALL`, `--network=none`, `--read-only` |
|
|
126
|
+
| 📊 **Risk Scorer** | Scores MCP servers LOW / MEDIUM / HIGH based on tool capabilities |
|
|
127
|
+
| 🖥️ **Live Dashboard** | Real-time web UI showing live block/allow feed at `/dashboard` |
|
|
128
|
+
| ⚡ **CLI** | `mcpshield inspect`, `mcpshield audit`, `mcpshield stats`, `mcpshield risk` |
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Policies
|
|
133
|
+
|
|
134
|
+
Policies are simple YAML files. Drop one in `policies/` and reference it by name.
|
|
135
|
+
|
|
136
|
+
```yaml
|
|
137
|
+
# policies/default.yaml
|
|
138
|
+
allowed_tools:
|
|
139
|
+
- safe_tool
|
|
140
|
+
- list_files
|
|
141
|
+
- get_time
|
|
142
|
+
|
|
143
|
+
block_network: true
|
|
144
|
+
block_env_access: true
|
|
145
|
+
|
|
146
|
+
blocked_arg_patterns:
|
|
147
|
+
- "169.254.169.254" # AWS metadata SSRF
|
|
148
|
+
- "169.254.170.2" # ECS metadata SSRF
|
|
149
|
+
- "localhost"
|
|
150
|
+
- "127.0.0.1"
|
|
151
|
+
- "/etc/passwd"
|
|
152
|
+
- "/etc/shadow"
|
|
153
|
+
- "file://"
|
|
154
|
+
- "gopher://"
|
|
155
|
+
|
|
156
|
+
max_memory_mb: 256
|
|
157
|
+
execution_timeout_seconds: 30
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Switch policy per server:
|
|
161
|
+
```bash
|
|
162
|
+
POST /inspect → { "policy": "strict", ... }
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Architecture
|
|
168
|
+
|
|
169
|
+
```
|
|
170
|
+
mcp-shield/
|
|
171
|
+
├── runtime/
|
|
172
|
+
│ ├── api/
|
|
173
|
+
│ │ └── main.py # FastAPI — /inspect /audit /sandbox /dashboard
|
|
174
|
+
│ ├── policy_engine.py # YAML policy loader + evaluator
|
|
175
|
+
│ ├── audit_logger.py # SQLite decision log
|
|
176
|
+
│ ├── risk_scorer.py # LOW/MEDIUM/HIGH risk scoring
|
|
177
|
+
│ ├── cli.py # Typer CLI — inspect/audit/stats/risk
|
|
178
|
+
│ ├── models.py # Pydantic schemas
|
|
179
|
+
│ └── sandbox/
|
|
180
|
+
│ ├── base.py # Abstract backend interface
|
|
181
|
+
│ └── docker_backend.py # Hardened Docker sandbox
|
|
182
|
+
├── policies/
|
|
183
|
+
│ ├── default.yaml # Standard policy
|
|
184
|
+
│ └── strict.yaml # Zero-trust policy
|
|
185
|
+
├── examples/
|
|
186
|
+
│ ├── malicious_mcp_server/ # Demo attacker (SSRF + secret theft + exec)
|
|
187
|
+
│ └── safe_mcp_server/ # Demo benign server
|
|
188
|
+
└── tests/ # 12 tests — all passing
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## Quickstart
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
# 1. Clone
|
|
197
|
+
git clone https://github.com/srisowmya2000/mcp-shield
|
|
198
|
+
cd mcp-shield
|
|
199
|
+
|
|
200
|
+
# 2. Install
|
|
201
|
+
python3 -m venv .venv && source .venv/bin/activate
|
|
202
|
+
pip install fastapi uvicorn pydantic pydantic-settings mcp httpx pyyaml
|
|
203
|
+
|
|
204
|
+
# 3. Start
|
|
205
|
+
uvicorn runtime.api.main:app --reload
|
|
206
|
+
|
|
207
|
+
# 4. Open
|
|
208
|
+
# API docs → http://localhost:8000/docs
|
|
209
|
+
# Dashboard → http://localhost:8000/dashboard
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## CLI
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
# Inspect a tool call
|
|
218
|
+
python3 -m runtime.cli inspect read_secrets
|
|
219
|
+
# → 🚫 BLOCKED — Tool 'read_secrets' is not in the allowed_tools list
|
|
220
|
+
|
|
221
|
+
# Score a server's risk
|
|
222
|
+
python3 -m runtime.cli risk "read_secrets,ssrf_fetch,safe_tool"
|
|
223
|
+
# → 🔴 HIGH RISK (score: 80)
|
|
224
|
+
|
|
225
|
+
# View audit log
|
|
226
|
+
python3 -m runtime.cli audit
|
|
227
|
+
|
|
228
|
+
# View stats
|
|
229
|
+
python3 -m runtime.cli stats
|
|
230
|
+
# → Total: 6 | Allowed: 2 | Blocked: 4 (67% block rate)
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## API Reference
|
|
236
|
+
|
|
237
|
+
| Endpoint | Method | Description |
|
|
238
|
+
|---|---|---|
|
|
239
|
+
| `/health` | GET | Service health check |
|
|
240
|
+
| `/inspect` | POST | Evaluate tool call → ALLOW / BLOCK |
|
|
241
|
+
| `/audit` | GET | Recent audit log entries |
|
|
242
|
+
| `/audit/stats` | GET | Total / allowed / blocked counts |
|
|
243
|
+
| `/risk/score` | POST | Score server risk by tool list |
|
|
244
|
+
| `/sandbox/launch` | POST | Launch MCP server in hardened Docker |
|
|
245
|
+
| `/sandbox/stop/{name}` | POST | Stop a running sandbox |
|
|
246
|
+
| `/sandbox/list` | GET | List running sandboxes |
|
|
247
|
+
| `/dashboard` | GET | Live real-time dashboard |
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
## Tests
|
|
252
|
+
|
|
253
|
+
```bash
|
|
254
|
+
pip install pytest
|
|
255
|
+
pytest tests/ -v
|
|
256
|
+
# 12 passed in 0.11s
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
Covers: tool allowlist blocking, SSRF argument detection, nested arg scanning, strict policy, edge cases.
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## Roadmap
|
|
264
|
+
|
|
265
|
+
- [x] Policy engine (allowlist + pattern scanning)
|
|
266
|
+
- [x] Audit logger (SQLite)
|
|
267
|
+
- [x] FastAPI REST surface
|
|
268
|
+
- [x] Docker sandbox backend (hardened)
|
|
269
|
+
- [x] Demo malicious MCP server
|
|
270
|
+
- [x] Risk scorer (LOW / MEDIUM / HIGH)
|
|
271
|
+
- [x] CLI (`mcpshield inspect`, `audit`, `stats`, `risk`)
|
|
272
|
+
- [x] Real-time dashboard
|
|
273
|
+
- [ ] Firecracker microVM backend
|
|
274
|
+
- [ ] PyPI package (`pip install mcp-shield`)
|
|
275
|
+
- [ ] `threat-model.md`
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
# mcp-shield 🛡️
|
|
2
|
+
|
|
3
|
+
> **The security runtime for MCP servers.**
|
|
4
|
+
> Every tool call inspected. Every attack blocked. Every decision logged.
|
|
5
|
+
|
|
6
|
+

|
|
7
|
+

|
|
8
|
+

|
|
9
|
+

|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## What is MCP?
|
|
14
|
+
|
|
15
|
+
**Model Context Protocol (MCP)** is an open standard that lets AI assistants (like Claude, Cursor, Copilot) connect to external tools and services — file systems, APIs, databases, browsers — through **MCP servers**.
|
|
16
|
+
|
|
17
|
+
Think of MCP servers as plugins that give AI agents real-world capabilities.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## The Problem
|
|
22
|
+
|
|
23
|
+
MCP servers run as **trusted processes** on your machine with access to:
|
|
24
|
+
|
|
25
|
+
| Access | Risk |
|
|
26
|
+
|---|---|
|
|
27
|
+
| 🗂️ Your filesystem | Read `/etc/passwd`, steal SSH keys |
|
|
28
|
+
| 🌐 Your network | SSRF to `169.254.169.254` (AWS metadata) |
|
|
29
|
+
| 🔑 Your environment variables | Steal API keys, tokens, secrets |
|
|
30
|
+
| ⚙️ Shell execution | Run arbitrary commands |
|
|
31
|
+
|
|
32
|
+
**A malicious or compromised MCP server can silently exfiltrate your secrets, pivot to internal infrastructure, or execute code — and you'd never know.**
|
|
33
|
+
|
|
34
|
+
This is not theoretical. A real SSRF vulnerability was found in an MCP OAuth HTTP transport implementation that allowed exactly this class of attack.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## How mcp-shield Fixes This
|
|
39
|
+
|
|
40
|
+
mcp-shield sits **between your AI agent and the MCP server** as a policy enforcement layer.
|
|
41
|
+
Before any tool executes, mcp-shield evaluates it. If it's not allowed — it's blocked.
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
AI Agent
|
|
45
|
+
│
|
|
46
|
+
▼
|
|
47
|
+
mcp-shield /inspect
|
|
48
|
+
│
|
|
49
|
+
├── Tool allowlist check → "read_secrets" not allowed → 🚫 BLOCK
|
|
50
|
+
├── Blocked pattern check → "ssrf_fetch" is dangerous → 🚫 BLOCK
|
|
51
|
+
├── Argument scanning → "169.254.169.254" in args → 🚫 BLOCK
|
|
52
|
+
│
|
|
53
|
+
└── Passed all checks → ✅ ALLOW → MCP Server executes
|
|
54
|
+
│
|
|
55
|
+
▼
|
|
56
|
+
Audit Log (SQLite)
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Every decision — ALLOW or BLOCK — is logged with a full audit trail.
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Live Demo
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# Start mcp-shield
|
|
67
|
+
uvicorn runtime.api.main:app --reload
|
|
68
|
+
|
|
69
|
+
# 🚫 Attempt secret theft → BLOCKED
|
|
70
|
+
curl -X POST http://localhost:8000/inspect \
|
|
71
|
+
-H "Content-Type: application/json" \
|
|
72
|
+
-d '{"server_name":"evil","policy":"default","tool_call":{"tool_name":"read_secrets","arguments":{}}}'
|
|
73
|
+
|
|
74
|
+
# → {"decision":"BLOCK","reason":"Tool 'read_secrets' is not in the allowed_tools list","blocked":true}
|
|
75
|
+
|
|
76
|
+
# 🚫 Attempt SSRF to AWS metadata endpoint → BLOCKED
|
|
77
|
+
curl -X POST http://localhost:8000/inspect \
|
|
78
|
+
-H "Content-Type: application/json" \
|
|
79
|
+
-d '{"server_name":"evil","policy":"default","tool_call":{"tool_name":"ssrf_fetch","arguments":{"url":"http://169.254.169.254/latest/meta-data/"}}}'
|
|
80
|
+
|
|
81
|
+
# → {"decision":"BLOCK","reason":"Argument contains blocked pattern: '169.254.169.254'","blocked":true}
|
|
82
|
+
|
|
83
|
+
# ✅ Safe tool → ALLOWED
|
|
84
|
+
curl -X POST http://localhost:8000/inspect \
|
|
85
|
+
-H "Content-Type: application/json" \
|
|
86
|
+
-d '{"server_name":"safe","policy":"default","tool_call":{"tool_name":"safe_tool","arguments":{"name":"Sri"}}}'
|
|
87
|
+
|
|
88
|
+
# → {"decision":"ALLOW","reason":"Passed all policy checks","blocked":false}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Key Features
|
|
94
|
+
|
|
95
|
+
| Feature | Description |
|
|
96
|
+
|---|---|
|
|
97
|
+
| 🔒 **Policy Engine** | YAML-based allowlists + blocked patterns, per-server policies |
|
|
98
|
+
| 🔍 **Argument Scanning** | Recursively scans nested args for SSRF, path traversal, dangerous patterns |
|
|
99
|
+
| 📋 **Audit Logger** | Every decision logged to SQLite with timestamp, server, tool, reason |
|
|
100
|
+
| 🐳 **Docker Sandbox** | Hardened containers: `--cap-drop=ALL`, `--network=none`, `--read-only` |
|
|
101
|
+
| 📊 **Risk Scorer** | Scores MCP servers LOW / MEDIUM / HIGH based on tool capabilities |
|
|
102
|
+
| 🖥️ **Live Dashboard** | Real-time web UI showing live block/allow feed at `/dashboard` |
|
|
103
|
+
| ⚡ **CLI** | `mcpshield inspect`, `mcpshield audit`, `mcpshield stats`, `mcpshield risk` |
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Policies
|
|
108
|
+
|
|
109
|
+
Policies are simple YAML files. Drop one in `policies/` and reference it by name.
|
|
110
|
+
|
|
111
|
+
```yaml
|
|
112
|
+
# policies/default.yaml
|
|
113
|
+
allowed_tools:
|
|
114
|
+
- safe_tool
|
|
115
|
+
- list_files
|
|
116
|
+
- get_time
|
|
117
|
+
|
|
118
|
+
block_network: true
|
|
119
|
+
block_env_access: true
|
|
120
|
+
|
|
121
|
+
blocked_arg_patterns:
|
|
122
|
+
- "169.254.169.254" # AWS metadata SSRF
|
|
123
|
+
- "169.254.170.2" # ECS metadata SSRF
|
|
124
|
+
- "localhost"
|
|
125
|
+
- "127.0.0.1"
|
|
126
|
+
- "/etc/passwd"
|
|
127
|
+
- "/etc/shadow"
|
|
128
|
+
- "file://"
|
|
129
|
+
- "gopher://"
|
|
130
|
+
|
|
131
|
+
max_memory_mb: 256
|
|
132
|
+
execution_timeout_seconds: 30
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Switch policy per server:
|
|
136
|
+
```bash
|
|
137
|
+
POST /inspect → { "policy": "strict", ... }
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Architecture
|
|
143
|
+
|
|
144
|
+
```
|
|
145
|
+
mcp-shield/
|
|
146
|
+
├── runtime/
|
|
147
|
+
│ ├── api/
|
|
148
|
+
│ │ └── main.py # FastAPI — /inspect /audit /sandbox /dashboard
|
|
149
|
+
│ ├── policy_engine.py # YAML policy loader + evaluator
|
|
150
|
+
│ ├── audit_logger.py # SQLite decision log
|
|
151
|
+
│ ├── risk_scorer.py # LOW/MEDIUM/HIGH risk scoring
|
|
152
|
+
│ ├── cli.py # Typer CLI — inspect/audit/stats/risk
|
|
153
|
+
│ ├── models.py # Pydantic schemas
|
|
154
|
+
│ └── sandbox/
|
|
155
|
+
│ ├── base.py # Abstract backend interface
|
|
156
|
+
│ └── docker_backend.py # Hardened Docker sandbox
|
|
157
|
+
├── policies/
|
|
158
|
+
│ ├── default.yaml # Standard policy
|
|
159
|
+
│ └── strict.yaml # Zero-trust policy
|
|
160
|
+
├── examples/
|
|
161
|
+
│ ├── malicious_mcp_server/ # Demo attacker (SSRF + secret theft + exec)
|
|
162
|
+
│ └── safe_mcp_server/ # Demo benign server
|
|
163
|
+
└── tests/ # 12 tests — all passing
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Quickstart
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
# 1. Clone
|
|
172
|
+
git clone https://github.com/srisowmya2000/mcp-shield
|
|
173
|
+
cd mcp-shield
|
|
174
|
+
|
|
175
|
+
# 2. Install
|
|
176
|
+
python3 -m venv .venv && source .venv/bin/activate
|
|
177
|
+
pip install fastapi uvicorn pydantic pydantic-settings mcp httpx pyyaml
|
|
178
|
+
|
|
179
|
+
# 3. Start
|
|
180
|
+
uvicorn runtime.api.main:app --reload
|
|
181
|
+
|
|
182
|
+
# 4. Open
|
|
183
|
+
# API docs → http://localhost:8000/docs
|
|
184
|
+
# Dashboard → http://localhost:8000/dashboard
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## CLI
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
# Inspect a tool call
|
|
193
|
+
python3 -m runtime.cli inspect read_secrets
|
|
194
|
+
# → 🚫 BLOCKED — Tool 'read_secrets' is not in the allowed_tools list
|
|
195
|
+
|
|
196
|
+
# Score a server's risk
|
|
197
|
+
python3 -m runtime.cli risk "read_secrets,ssrf_fetch,safe_tool"
|
|
198
|
+
# → 🔴 HIGH RISK (score: 80)
|
|
199
|
+
|
|
200
|
+
# View audit log
|
|
201
|
+
python3 -m runtime.cli audit
|
|
202
|
+
|
|
203
|
+
# View stats
|
|
204
|
+
python3 -m runtime.cli stats
|
|
205
|
+
# → Total: 6 | Allowed: 2 | Blocked: 4 (67% block rate)
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## API Reference
|
|
211
|
+
|
|
212
|
+
| Endpoint | Method | Description |
|
|
213
|
+
|---|---|---|
|
|
214
|
+
| `/health` | GET | Service health check |
|
|
215
|
+
| `/inspect` | POST | Evaluate tool call → ALLOW / BLOCK |
|
|
216
|
+
| `/audit` | GET | Recent audit log entries |
|
|
217
|
+
| `/audit/stats` | GET | Total / allowed / blocked counts |
|
|
218
|
+
| `/risk/score` | POST | Score server risk by tool list |
|
|
219
|
+
| `/sandbox/launch` | POST | Launch MCP server in hardened Docker |
|
|
220
|
+
| `/sandbox/stop/{name}` | POST | Stop a running sandbox |
|
|
221
|
+
| `/sandbox/list` | GET | List running sandboxes |
|
|
222
|
+
| `/dashboard` | GET | Live real-time dashboard |
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## Tests
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
pip install pytest
|
|
230
|
+
pytest tests/ -v
|
|
231
|
+
# 12 passed in 0.11s
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Covers: tool allowlist blocking, SSRF argument detection, nested arg scanning, strict policy, edge cases.
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## Roadmap
|
|
239
|
+
|
|
240
|
+
- [x] Policy engine (allowlist + pattern scanning)
|
|
241
|
+
- [x] Audit logger (SQLite)
|
|
242
|
+
- [x] FastAPI REST surface
|
|
243
|
+
- [x] Docker sandbox backend (hardened)
|
|
244
|
+
- [x] Demo malicious MCP server
|
|
245
|
+
- [x] Risk scorer (LOW / MEDIUM / HIGH)
|
|
246
|
+
- [x] CLI (`mcpshield inspect`, `audit`, `stats`, `risk`)
|
|
247
|
+
- [x] Real-time dashboard
|
|
248
|
+
- [ ] Firecracker microVM backend
|
|
249
|
+
- [ ] PyPI package (`pip install mcp-shield`)
|
|
250
|
+
- [ ] `threat-model.md`
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
|