mcp-fence 0.1.0
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.
- package/LICENSE +21 -0
- package/README.md +309 -0
- package/dist/cli.js +1963 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +537 -0
- package/dist/index.js +1733 -0
- package/dist/index.js.map +1 -0
- package/package.json +67 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 yjcho
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
# mcp-fence
|
|
2
|
+
|
|
3
|
+
**The bidirectional firewall for MCP** -- scans inputs AND outputs, detects rug-pulls at runtime, zero config.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/mcp-fence)
|
|
6
|
+
[](./LICENSE)
|
|
7
|
+
[](https://nodejs.org/)
|
|
8
|
+
[](#owasp-mcp-top-10-coverage)
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Why mcp-fence?
|
|
13
|
+
|
|
14
|
+
Most MCP security tools only inspect what goes **in** to a server. That misses half the attack surface.
|
|
15
|
+
|
|
16
|
+
- **Bidirectional scanning** -- Inspects both requests and responses. A compromised server can inject instructions in its output; mcp-fence catches that.
|
|
17
|
+
- **Rug-pull detection** -- Pins tool descriptions by hash at first approval. If a server silently changes what a tool does at runtime, mcp-fence flags it immediately.
|
|
18
|
+
- **Zero config** -- Works out of the box with secure defaults (monitor mode). No YAML required to get started.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Quick Start
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# Install globally
|
|
26
|
+
npm install -g mcp-fence
|
|
27
|
+
|
|
28
|
+
# Proxy any MCP server
|
|
29
|
+
mcp-fence start -- npx @anthropic/mcp-server-filesystem /tmp
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Or run without installing:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npx mcp-fence start -- npx @anthropic/mcp-server-filesystem /tmp
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
That's it. mcp-fence sits between your MCP client and server, logging every suspicious finding to stderr and an SQLite audit trail.
|
|
39
|
+
|
|
40
|
+
### Claude Desktop Integration
|
|
41
|
+
|
|
42
|
+
Add mcp-fence as a wrapper in your `claude_desktop_config.json`:
|
|
43
|
+
|
|
44
|
+
```json
|
|
45
|
+
{
|
|
46
|
+
"mcpServers": {
|
|
47
|
+
"filesystem": {
|
|
48
|
+
"command": "npx",
|
|
49
|
+
"args": [
|
|
50
|
+
"mcp-fence",
|
|
51
|
+
"start",
|
|
52
|
+
"--mode", "enforce",
|
|
53
|
+
"--",
|
|
54
|
+
"npx", "@anthropic/mcp-server-filesystem", "/tmp"
|
|
55
|
+
]
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Your MCP server works exactly as before. mcp-fence just inspects traffic passing through.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Features
|
|
66
|
+
|
|
67
|
+
| Feature | Description |
|
|
68
|
+
|---------|-------------|
|
|
69
|
+
| **Bidirectional scanning** | Scans both client requests and server responses for threats |
|
|
70
|
+
| **Prompt injection detection** | 20+ regex patterns covering instruction override, role hijacking, hidden instructions, multi-language attacks |
|
|
71
|
+
| **Secret leak detection** | 25+ patterns for AWS keys, GitHub tokens, private keys, connection strings, and more |
|
|
72
|
+
| **Rug-pull detection** | SHA-256 hash pinning of tool descriptions. Detects silent modification after initial approval |
|
|
73
|
+
| **Policy engine** | Tool-level allow/deny rules with glob patterns and argument validation |
|
|
74
|
+
| **Audit logging** | SQLite-backed event log with queryable CLI |
|
|
75
|
+
| **SARIF output** | Export findings in SARIF format for GitHub Security tab integration |
|
|
76
|
+
| **Zero-config defaults** | Monitor mode out of the box -- logs threats without blocking, so you never break a working setup |
|
|
77
|
+
|
|
78
|
+
### Limitations (v0.1)
|
|
79
|
+
|
|
80
|
+
Detection is regex-based. It handles known patterns well but won't catch novel prompt injection via paraphrase or synonyms. ML-based semantic detection is planned for v0.4. Only stdio transport is supported; SSE and Streamable HTTP are coming in v0.3.
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## OWASP MCP Top 10 Coverage
|
|
85
|
+
|
|
86
|
+
| ID | Risk | v0.1 | How |
|
|
87
|
+
|----|------|:----:|-----|
|
|
88
|
+
| MCP01 | Token/Secret Exposure | Yes | Secret pattern detection in requests and responses |
|
|
89
|
+
| MCP02 | Tool Poisoning | Yes | Tool description hash pinning (rug-pull detection) |
|
|
90
|
+
| MCP03 | Excessive Permissions | Yes | Policy engine with tool allow/deny + argument constraints |
|
|
91
|
+
| MCP04 | Command Injection | Yes | Command injection patterns in detection engine |
|
|
92
|
+
| MCP05 | Insecure Data Handling | -- | Planned for v0.2 |
|
|
93
|
+
| MCP06 | Insufficient Logging | Yes | SQLite audit log + SARIF export |
|
|
94
|
+
| MCP07 | Insufficient Auth | Yes | Policy enforcement + tool-level access control |
|
|
95
|
+
| MCP08 | Server Spoofing | -- | Planned for v0.2 |
|
|
96
|
+
| MCP09 | Supply Chain Compromise | -- | Planned for v0.2 |
|
|
97
|
+
| MCP10 | Context Injection | -- | Planned for v0.2 |
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Configuration
|
|
102
|
+
|
|
103
|
+
Generate a config file:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
mcp-fence init
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
This creates `fence.config.yaml`:
|
|
110
|
+
|
|
111
|
+
```yaml
|
|
112
|
+
# Operation mode: "monitor" (log only) or "enforce" (block threats)
|
|
113
|
+
mode: monitor
|
|
114
|
+
|
|
115
|
+
log:
|
|
116
|
+
level: info
|
|
117
|
+
# file: ./mcp-fence.log # uncomment to log to file
|
|
118
|
+
|
|
119
|
+
detection:
|
|
120
|
+
warnThreshold: 0.5 # score >= 0.5 triggers a warning
|
|
121
|
+
blockThreshold: 0.8 # score >= 0.8 triggers a block (enforce mode only)
|
|
122
|
+
maxInputSize: 10240 # bytes — inputs larger than this are truncated
|
|
123
|
+
|
|
124
|
+
policy:
|
|
125
|
+
defaultAction: allow
|
|
126
|
+
rules:
|
|
127
|
+
- tool: "exec_cmd"
|
|
128
|
+
action: deny
|
|
129
|
+
- tool: "read_file"
|
|
130
|
+
action: allow
|
|
131
|
+
args:
|
|
132
|
+
- name: path
|
|
133
|
+
denyPattern: "^\\.env$|^/etc/"
|
|
134
|
+
- tool: "write_*"
|
|
135
|
+
action: deny
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Config priority: **CLI flags > environment variables > YAML file > defaults**.
|
|
139
|
+
|
|
140
|
+
Environment variables: `MCP_FENCE_MODE` (`monitor` | `enforce`), `MCP_FENCE_LOG_LEVEL` (`debug` | `info` | `warn` | `error`).
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## CLI Commands
|
|
145
|
+
|
|
146
|
+
### `start` -- Run the security proxy
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
# Basic usage
|
|
150
|
+
mcp-fence start -- npx @anthropic/mcp-server-filesystem /tmp
|
|
151
|
+
|
|
152
|
+
# With options
|
|
153
|
+
mcp-fence start --mode enforce --config ./fence.config.yaml -- node my-server.js
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### `init` -- Generate default config
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
mcp-fence init
|
|
160
|
+
mcp-fence init --output ./custom-config.yaml
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### `scan` -- Standalone threat scan (no proxy needed)
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
# Scan a file
|
|
167
|
+
mcp-fence scan ./suspicious-prompt.txt
|
|
168
|
+
|
|
169
|
+
# Scan inline text
|
|
170
|
+
mcp-fence scan --text "ignore all previous instructions"
|
|
171
|
+
|
|
172
|
+
# Scan server responses
|
|
173
|
+
mcp-fence scan ./response.json --direction response
|
|
174
|
+
|
|
175
|
+
# Output as JSON or SARIF
|
|
176
|
+
mcp-fence scan ./file.txt --format json
|
|
177
|
+
mcp-fence scan ./file.txt --format sarif > results.sarif
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### `logs` -- Query the audit trail
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
# Recent warnings
|
|
184
|
+
mcp-fence logs --since 1h --level warn
|
|
185
|
+
|
|
186
|
+
# Export to SARIF for GitHub
|
|
187
|
+
mcp-fence logs --format sarif > audit.sarif
|
|
188
|
+
|
|
189
|
+
# Filter by direction
|
|
190
|
+
mcp-fence logs --direction response --limit 50
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### `status` -- Show config and capabilities
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
mcp-fence status
|
|
197
|
+
mcp-fence status --config ./fence.config.yaml
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## Architecture
|
|
203
|
+
|
|
204
|
+
```
|
|
205
|
+
mcp-fence
|
|
206
|
+
┌─────────────────────┐
|
|
207
|
+
[MCP Client] ──> │ 1. Detection Engine │ ──> [MCP Server]
|
|
208
|
+
stdin│ 2. Hash Pin Check │stdout
|
|
209
|
+
[MCP Client] <── │ 3. Policy Engine │ <── [MCP Server]
|
|
210
|
+
│ 4. Audit Logger │
|
|
211
|
+
└─────────────────────┘
|
|
212
|
+
│
|
|
213
|
+
[SQLite Audit DB]
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Every message flows through the same pipeline:
|
|
217
|
+
|
|
218
|
+
1. **Intercept** -- Proxy captures the JSON-RPC message (request or response).
|
|
219
|
+
2. **Detect** -- Detection engine runs injection, secret, and command-injection patterns against the message content.
|
|
220
|
+
3. **Pin check** -- For `tools/list` responses, hash-pins tool descriptions and flags any changes.
|
|
221
|
+
4. **Policy** -- Policy engine evaluates tool-level allow/deny rules and argument constraints.
|
|
222
|
+
5. **Audit** -- Every scan result is logged to SQLite with timestamp, direction, decision, and findings.
|
|
223
|
+
6. **Forward or block** -- In monitor mode, everything passes through (findings are logged). In enforce mode, messages exceeding the block threshold are rejected.
|
|
224
|
+
|
|
225
|
+
Modules are decoupled: detection doesn't import policy, audit doesn't import detection. The proxy orchestrates all communication between them through the `ScanResult` contract.
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## Programmatic Usage
|
|
230
|
+
|
|
231
|
+
mcp-fence can be used as a library in your own Node.js applications:
|
|
232
|
+
|
|
233
|
+
```typescript
|
|
234
|
+
import {
|
|
235
|
+
McpProxy,
|
|
236
|
+
DetectionEngine,
|
|
237
|
+
HashPinChecker,
|
|
238
|
+
MemoryHashStore,
|
|
239
|
+
PolicyEngine,
|
|
240
|
+
AuditLoggerImpl,
|
|
241
|
+
SqliteAuditStore,
|
|
242
|
+
loadConfig,
|
|
243
|
+
} from 'mcp-fence';
|
|
244
|
+
|
|
245
|
+
const config = loadConfig('./fence.config.yaml');
|
|
246
|
+
|
|
247
|
+
const proxy = new McpProxy({
|
|
248
|
+
serverCommand: 'npx',
|
|
249
|
+
serverArgs: ['@anthropic/mcp-server-filesystem', '/tmp'],
|
|
250
|
+
config,
|
|
251
|
+
scanner: new DetectionEngine(config.detection),
|
|
252
|
+
hashPinChecker: new HashPinChecker(new MemoryHashStore()),
|
|
253
|
+
policyEngine: new PolicyEngine(config.policy),
|
|
254
|
+
auditLogger: new AuditLoggerImpl(new SqliteAuditStore('./audit.db')),
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
await proxy.start();
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
You can also use the detection engine standalone:
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
import { DetectionEngine, DEFAULT_CONFIG } from 'mcp-fence';
|
|
264
|
+
|
|
265
|
+
const engine = new DetectionEngine(DEFAULT_CONFIG.detection);
|
|
266
|
+
|
|
267
|
+
const result = await engine.scan(
|
|
268
|
+
{ jsonrpc: '2.0', id: 1, method: 'tools/call', params: { name: 'read_file', arguments: { path: '/etc/passwd' } } },
|
|
269
|
+
'request'
|
|
270
|
+
);
|
|
271
|
+
|
|
272
|
+
console.log(result.decision); // 'allow' | 'warn' | 'block'
|
|
273
|
+
console.log(result.findings); // Finding[]
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
## Roadmap
|
|
279
|
+
|
|
280
|
+
| Version | Focus |
|
|
281
|
+
|---------|-------|
|
|
282
|
+
| **v0.1** | stdio proxy, bidirectional scanning, secret detection, hash pinning, policy engine, SQLite audit, SARIF, CLI |
|
|
283
|
+
| **v0.2** | Audit log hardening (secret masking, HMAC integrity, DB size limits), shadow tool detection, Unicode normalization for arguments |
|
|
284
|
+
| **v0.3** | SSE + Streamable HTTP transport, JWT authentication, OPA policy server integration |
|
|
285
|
+
| **v0.4** | ML-based semantic detection (embedding similarity), session-level multi-step analysis |
|
|
286
|
+
| **v1.0** | Production-stable release |
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
## Contributing
|
|
291
|
+
|
|
292
|
+
Contributions are welcome. Please open an issue before submitting large changes so we can discuss the approach.
|
|
293
|
+
|
|
294
|
+
```bash
|
|
295
|
+
git clone https://github.com/user/mcp-fence.git
|
|
296
|
+
cd mcp-fence
|
|
297
|
+
npm install
|
|
298
|
+
npm test # run tests
|
|
299
|
+
npm run typecheck # type checking
|
|
300
|
+
npm run lint # lint
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
Security-critical modules (`src/detection/`, `src/integrity/`, `src/policy/local.ts`) require manual review on every PR. No exceptions.
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
## License
|
|
308
|
+
|
|
309
|
+
[MIT](./LICENSE)
|