agent-mcp-guard 0.3.0 → 0.3.1
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/README.md +18 -9
- package/action.yml +1 -1
- package/docs/business-playbook.md +5 -3
- package/docs/examples/e2e-example.md +60 -0
- package/docs/github-action.md +5 -3
- package/docs/launch-checklist.md +11 -1
- package/docs/marketplace-action-readme.md +91 -0
- package/docs/marketplace.md +119 -0
- package/docs/operator-runbook.md +1 -1
- package/docs/paid-audit.md +6 -4
- package/docs/roadmap.md +1 -1
- package/package.json +4 -1
- package/scripts/prepare-marketplace-action.js +72 -0
- package/site/e2e/claude_desktop_config.json +28 -0
- package/site/e2e/index.html +106 -0
- package/site/e2e/report.html +440 -0
- package/site/e2e/report.json +148 -0
- package/site/e2e/report.md +47 -0
- package/site/e2e/report.sarif +570 -0
- package/src/cli.js +1 -1
- package/src/report.js +12 -4
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
+
<title>mcp-guard E2E Example</title>
|
|
7
|
+
<meta name="description" content="A transparent end-to-end mcp-guard example with committed input, reproducible CLI commands, and generated reports.">
|
|
8
|
+
<link rel="icon" href="../assets/brand-mark.svg" type="image/svg+xml">
|
|
9
|
+
<link rel="stylesheet" href="../styles.css">
|
|
10
|
+
</head>
|
|
11
|
+
<body>
|
|
12
|
+
<header class="site-header">
|
|
13
|
+
<a class="brand" href="../" aria-label="mcp-guard home">
|
|
14
|
+
<img src="../assets/brand-mark.svg" alt="">
|
|
15
|
+
<span>mcp-guard</span>
|
|
16
|
+
</a>
|
|
17
|
+
<nav aria-label="Primary navigation">
|
|
18
|
+
<a href="../#scan">Scan</a>
|
|
19
|
+
<a href="../#action">Action</a>
|
|
20
|
+
<a href="../#reports">Reports</a>
|
|
21
|
+
<a href="../#pilot">Pilot</a>
|
|
22
|
+
<a class="github-link" href="https://github.com/ChaoYue0307/mcp-guard">GitHub</a>
|
|
23
|
+
</nav>
|
|
24
|
+
</header>
|
|
25
|
+
|
|
26
|
+
<main>
|
|
27
|
+
<section class="example-hero">
|
|
28
|
+
<div>
|
|
29
|
+
<span class="eyebrow">End-to-end proof</span>
|
|
30
|
+
<h1>Real scanner output from a reproducible MCP config.</h1>
|
|
31
|
+
<p>The input is synthetic so it is safe to publish, but every report below was generated by the current `mcp-guard` CLI from the committed config file.</p>
|
|
32
|
+
</div>
|
|
33
|
+
<div class="example-score">
|
|
34
|
+
<span>Risk Score</span>
|
|
35
|
+
<strong>98</strong>
|
|
36
|
+
<p>9 findings across 3 MCP servers</p>
|
|
37
|
+
</div>
|
|
38
|
+
</section>
|
|
39
|
+
|
|
40
|
+
<section class="example-layout">
|
|
41
|
+
<div class="example-main">
|
|
42
|
+
<h2>1. Input config</h2>
|
|
43
|
+
<p>The config intentionally includes risky patterns a real MCP setup can contain: remote package execution, root filesystem access, shell startup, remote MCP URL, and secret-like values.</p>
|
|
44
|
+
<pre><code>{
|
|
45
|
+
"mcpServers": {
|
|
46
|
+
"filesystem-all-home": {
|
|
47
|
+
"command": "npx",
|
|
48
|
+
"args": ["@modelcontextprotocol/server-filesystem", "/"],
|
|
49
|
+
"env": { "GITHUB_TOKEN": "ghp_exampleSecretValue1234567890" },
|
|
50
|
+
"cwd": "/"
|
|
51
|
+
},
|
|
52
|
+
"shell-installer": {
|
|
53
|
+
"command": "bash",
|
|
54
|
+
"args": ["-c", "curl https://example.com/install.sh | bash"]
|
|
55
|
+
},
|
|
56
|
+
"remote-prod": {
|
|
57
|
+
"url": "https://mcp.example.com/sse",
|
|
58
|
+
"headers": { "Authorization": "Bearer example-secret-token" }
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}</code></pre>
|
|
62
|
+
|
|
63
|
+
<h2>2. Reproduce the scan</h2>
|
|
64
|
+
<pre><code>node ./bin/mcp-guard.js scan --config site/e2e/claude_desktop_config.json --format markdown --output site/e2e/report.md
|
|
65
|
+
node ./bin/mcp-guard.js scan --config site/e2e/claude_desktop_config.json --format html --output site/e2e/report.html
|
|
66
|
+
node ./bin/mcp-guard.js scan --config site/e2e/claude_desktop_config.json --format json --output site/e2e/report.json
|
|
67
|
+
node ./bin/mcp-guard.js scan --config site/e2e/claude_desktop_config.json --format sarif --output site/e2e/report.sarif</code></pre>
|
|
68
|
+
|
|
69
|
+
<h2>3. What it found</h2>
|
|
70
|
+
<div class="finding-table">
|
|
71
|
+
<div><span>Critical</span><strong>MCP010</strong><p>Shell command executes inline script.</p></div>
|
|
72
|
+
<div><span>Critical</span><strong>MCP050</strong><p>Startup command includes curl-pipe-shell.</p></div>
|
|
73
|
+
<div><span>High</span><strong>MCP021</strong><p>Remote MCP package is not version pinned.</p></div>
|
|
74
|
+
<div><span>High</span><strong>MCP030</strong><p>Secret-like environment variable is exposed.</p></div>
|
|
75
|
+
<div><span>High</span><strong>MCP040/MCP041</strong><p>Working directory and argument grant broad filesystem access.</p></div>
|
|
76
|
+
<div><span>High</span><strong>MCP061</strong><p>Secret-like authorization header is configured.</p></div>
|
|
77
|
+
</div>
|
|
78
|
+
</div>
|
|
79
|
+
|
|
80
|
+
<aside class="example-side">
|
|
81
|
+
<h2>Generated artifacts</h2>
|
|
82
|
+
<p>Open these files and compare them with the input config.</p>
|
|
83
|
+
<a href="claude_desktop_config.json">Input JSON</a>
|
|
84
|
+
<a href="report.md">Markdown report</a>
|
|
85
|
+
<a href="report.html">HTML report</a>
|
|
86
|
+
<a href="report.json">JSON report</a>
|
|
87
|
+
<a href="report.sarif">SARIF report</a>
|
|
88
|
+
<h2>Output summary</h2>
|
|
89
|
+
<ul>
|
|
90
|
+
<li>Scanned files: 1</li>
|
|
91
|
+
<li>MCP servers: 3</li>
|
|
92
|
+
<li>Findings: 9</li>
|
|
93
|
+
<li>Critical: 2</li>
|
|
94
|
+
<li>High: 5</li>
|
|
95
|
+
<li>Medium: 2</li>
|
|
96
|
+
<li>Low: 0</li>
|
|
97
|
+
</ul>
|
|
98
|
+
</aside>
|
|
99
|
+
</section>
|
|
100
|
+
</main>
|
|
101
|
+
|
|
102
|
+
<footer>
|
|
103
|
+
<p>mcp-guard is Apache-2.0 open source. This example is generated from files committed in the repository.</p>
|
|
104
|
+
</footer>
|
|
105
|
+
</body>
|
|
106
|
+
</html>
|
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
+
<title>mcp-guard Scan Report</title>
|
|
7
|
+
<style>
|
|
8
|
+
:root {
|
|
9
|
+
color-scheme: light;
|
|
10
|
+
--bg: #f8fafc;
|
|
11
|
+
--panel: #ffffff;
|
|
12
|
+
--ink: #111827;
|
|
13
|
+
--muted: #5b6575;
|
|
14
|
+
--line: #d9e2ec;
|
|
15
|
+
--soft: #eef4f7;
|
|
16
|
+
--critical: #b91c1c;
|
|
17
|
+
--high: #c2410c;
|
|
18
|
+
--medium: #a16207;
|
|
19
|
+
--low: #0f766e;
|
|
20
|
+
--info: #1d4ed8;
|
|
21
|
+
--shadow: 0 20px 55px rgba(15, 23, 42, 0.08);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
* { box-sizing: border-box; }
|
|
25
|
+
|
|
26
|
+
body {
|
|
27
|
+
margin: 0;
|
|
28
|
+
background: var(--bg);
|
|
29
|
+
color: var(--ink);
|
|
30
|
+
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
31
|
+
line-height: 1.5;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
main {
|
|
35
|
+
width: min(1120px, calc(100% - 32px));
|
|
36
|
+
margin: 0 auto;
|
|
37
|
+
padding: 28px 0 48px;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.hero {
|
|
41
|
+
background: #ffffff;
|
|
42
|
+
border: 1px solid var(--line);
|
|
43
|
+
border-radius: 8px;
|
|
44
|
+
box-shadow: var(--shadow);
|
|
45
|
+
padding: 28px;
|
|
46
|
+
display: grid;
|
|
47
|
+
grid-template-columns: minmax(0, 1fr) 240px;
|
|
48
|
+
gap: 24px;
|
|
49
|
+
align-items: stretch;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.eyebrow {
|
|
53
|
+
margin: 0 0 8px;
|
|
54
|
+
color: var(--info);
|
|
55
|
+
font-size: 13px;
|
|
56
|
+
font-weight: 700;
|
|
57
|
+
letter-spacing: 0;
|
|
58
|
+
text-transform: uppercase;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
h1, h2 {
|
|
62
|
+
letter-spacing: 0;
|
|
63
|
+
line-height: 1.08;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
h1 {
|
|
67
|
+
margin: 0;
|
|
68
|
+
font-size: 34px;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
h2 {
|
|
72
|
+
margin: 0 0 14px;
|
|
73
|
+
font-size: 21px;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.lead {
|
|
77
|
+
max-width: 720px;
|
|
78
|
+
margin: 12px 0 0;
|
|
79
|
+
color: var(--muted);
|
|
80
|
+
font-size: 16px;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.scorecard {
|
|
84
|
+
border-radius: 8px;
|
|
85
|
+
border: 1px solid var(--line);
|
|
86
|
+
background: var(--soft);
|
|
87
|
+
padding: 18px;
|
|
88
|
+
min-height: 176px;
|
|
89
|
+
display: flex;
|
|
90
|
+
flex-direction: column;
|
|
91
|
+
justify-content: space-between;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.score-label {
|
|
95
|
+
margin: 0;
|
|
96
|
+
color: var(--muted);
|
|
97
|
+
font-size: 13px;
|
|
98
|
+
font-weight: 700;
|
|
99
|
+
text-transform: uppercase;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.score-value {
|
|
103
|
+
margin: 8px 0;
|
|
104
|
+
font-size: 58px;
|
|
105
|
+
font-weight: 800;
|
|
106
|
+
line-height: 1;
|
|
107
|
+
color: var(--critical);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.score-caption {
|
|
111
|
+
margin: 0;
|
|
112
|
+
color: var(--muted);
|
|
113
|
+
font-size: 14px;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.grid {
|
|
117
|
+
display: grid;
|
|
118
|
+
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
119
|
+
gap: 12px;
|
|
120
|
+
margin: 18px 0 0;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.metric {
|
|
124
|
+
background: var(--panel);
|
|
125
|
+
border: 1px solid var(--line);
|
|
126
|
+
border-radius: 8px;
|
|
127
|
+
padding: 14px;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.metric strong {
|
|
131
|
+
display: block;
|
|
132
|
+
font-size: 24px;
|
|
133
|
+
line-height: 1.1;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.metric span {
|
|
137
|
+
display: block;
|
|
138
|
+
margin-top: 6px;
|
|
139
|
+
color: var(--muted);
|
|
140
|
+
font-size: 13px;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
section {
|
|
144
|
+
margin-top: 22px;
|
|
145
|
+
background: var(--panel);
|
|
146
|
+
border: 1px solid var(--line);
|
|
147
|
+
border-radius: 8px;
|
|
148
|
+
box-shadow: 0 10px 30px rgba(15, 23, 42, 0.04);
|
|
149
|
+
padding: 22px;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.severity-row {
|
|
153
|
+
display: grid;
|
|
154
|
+
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
155
|
+
gap: 10px;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.severity {
|
|
159
|
+
border: 1px solid var(--line);
|
|
160
|
+
border-radius: 8px;
|
|
161
|
+
padding: 12px;
|
|
162
|
+
min-height: 78px;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.severity b {
|
|
166
|
+
display: block;
|
|
167
|
+
font-size: 22px;
|
|
168
|
+
line-height: 1.1;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.severity span {
|
|
172
|
+
display: block;
|
|
173
|
+
margin-top: 6px;
|
|
174
|
+
color: var(--muted);
|
|
175
|
+
font-size: 13px;
|
|
176
|
+
text-transform: capitalize;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.critical { color: var(--critical); }
|
|
180
|
+
.high { color: var(--high); }
|
|
181
|
+
.medium { color: var(--medium); }
|
|
182
|
+
.low { color: var(--low); }
|
|
183
|
+
|
|
184
|
+
.table-wrap {
|
|
185
|
+
width: 100%;
|
|
186
|
+
overflow-x: auto;
|
|
187
|
+
border: 1px solid var(--line);
|
|
188
|
+
border-radius: 8px;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
table {
|
|
192
|
+
width: 100%;
|
|
193
|
+
min-width: 760px;
|
|
194
|
+
border-collapse: collapse;
|
|
195
|
+
background: var(--panel);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
th, td {
|
|
199
|
+
padding: 12px 14px;
|
|
200
|
+
border-bottom: 1px solid var(--line);
|
|
201
|
+
text-align: left;
|
|
202
|
+
vertical-align: top;
|
|
203
|
+
font-size: 14px;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
th {
|
|
207
|
+
color: #374151;
|
|
208
|
+
background: #f1f5f9;
|
|
209
|
+
font-size: 12px;
|
|
210
|
+
text-transform: uppercase;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
tr:last-child td { border-bottom: 0; }
|
|
214
|
+
|
|
215
|
+
code {
|
|
216
|
+
padding: 2px 5px;
|
|
217
|
+
border-radius: 5px;
|
|
218
|
+
background: #eef2f7;
|
|
219
|
+
color: #111827;
|
|
220
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
|
|
221
|
+
font-size: 0.92em;
|
|
222
|
+
white-space: normal;
|
|
223
|
+
overflow-wrap: anywhere;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.pill {
|
|
227
|
+
display: inline-flex;
|
|
228
|
+
align-items: center;
|
|
229
|
+
min-height: 24px;
|
|
230
|
+
padding: 3px 8px;
|
|
231
|
+
border-radius: 999px;
|
|
232
|
+
background: #f1f5f9;
|
|
233
|
+
font-size: 12px;
|
|
234
|
+
font-weight: 700;
|
|
235
|
+
text-transform: uppercase;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
.pill.critical { background: #fee2e2; }
|
|
239
|
+
.pill.high { background: #ffedd5; }
|
|
240
|
+
.pill.medium { background: #fef3c7; }
|
|
241
|
+
.pill.low { background: #ccfbf1; }
|
|
242
|
+
|
|
243
|
+
.empty {
|
|
244
|
+
margin: 0;
|
|
245
|
+
color: var(--muted);
|
|
246
|
+
border: 1px dashed var(--line);
|
|
247
|
+
border-radius: 8px;
|
|
248
|
+
padding: 16px;
|
|
249
|
+
background: #fbfdff;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
.notes {
|
|
253
|
+
color: var(--muted);
|
|
254
|
+
font-size: 14px;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
.notes ul {
|
|
258
|
+
margin: 10px 0 0;
|
|
259
|
+
padding-left: 18px;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
@media (max-width: 780px) {
|
|
263
|
+
main {
|
|
264
|
+
width: min(100% - 20px, 1120px);
|
|
265
|
+
padding-top: 10px;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
.hero {
|
|
269
|
+
grid-template-columns: 1fr;
|
|
270
|
+
padding: 20px;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
h1 { font-size: 28px; }
|
|
274
|
+
|
|
275
|
+
.grid,
|
|
276
|
+
.severity-row {
|
|
277
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
@media (max-width: 460px) {
|
|
282
|
+
.grid,
|
|
283
|
+
.severity-row {
|
|
284
|
+
grid-template-columns: 1fr;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
</style>
|
|
288
|
+
</head>
|
|
289
|
+
<body>
|
|
290
|
+
<main>
|
|
291
|
+
<header class="hero">
|
|
292
|
+
<div>
|
|
293
|
+
<p class="eyebrow">mcp-guard scan report</p>
|
|
294
|
+
<h1>AI agent tool risk review</h1>
|
|
295
|
+
<p class="lead">Local-first review of MCP server configuration, startup commands, remote endpoints, filesystem scope, and secret-like values.</p>
|
|
296
|
+
<div class="grid">
|
|
297
|
+
<div class="metric"><strong>1</strong><span>Scanned files</span></div>
|
|
298
|
+
<div class="metric"><strong>3</strong><span>MCP servers</span></div>
|
|
299
|
+
<div class="metric"><strong>9</strong><span>Findings</span></div>
|
|
300
|
+
<div class="metric"><strong>2026-05-10 09:16 UTC</strong><span>Generated</span></div>
|
|
301
|
+
</div>
|
|
302
|
+
</div>
|
|
303
|
+
<aside class="scorecard" aria-label="Risk score">
|
|
304
|
+
<div>
|
|
305
|
+
<p class="score-label">Risk score</p>
|
|
306
|
+
<p class="score-value">98</p>
|
|
307
|
+
</div>
|
|
308
|
+
<p class="score-caption">Critical review recommended before enabling these tools.</p>
|
|
309
|
+
</aside>
|
|
310
|
+
</header>
|
|
311
|
+
|
|
312
|
+
<section>
|
|
313
|
+
<h2>Severity Summary</h2>
|
|
314
|
+
<div class="severity-row">
|
|
315
|
+
<div class="severity critical"><b>2</b><span>critical</span></div>
|
|
316
|
+
<div class="severity high"><b>5</b><span>high</span></div>
|
|
317
|
+
<div class="severity medium"><b>2</b><span>medium</span></div>
|
|
318
|
+
<div class="severity low"><b>0</b><span>low</span></div>
|
|
319
|
+
</div>
|
|
320
|
+
</section>
|
|
321
|
+
|
|
322
|
+
<section>
|
|
323
|
+
<h2>Scanned Files</h2>
|
|
324
|
+
<div class="table-wrap"><table><thead><tr><th>Path</th></tr></thead><tbody><tr><td><code>site/e2e/claude_desktop_config.json</code></td></tr></tbody></table></div>
|
|
325
|
+
</section>
|
|
326
|
+
|
|
327
|
+
<section>
|
|
328
|
+
<h2>MCP Server Inventory</h2>
|
|
329
|
+
<div class="table-wrap"><table>
|
|
330
|
+
<thead><tr><th>Server</th><th>Command</th><th>Args</th><th>CWD</th><th>URL</th><th>Env</th><th>Headers</th></tr></thead>
|
|
331
|
+
<tbody><tr>
|
|
332
|
+
<td><strong>filesystem-all-home</strong><br><code>site/e2e/claude_desktop_config.json</code></td>
|
|
333
|
+
<td><code>npx</code></td>
|
|
334
|
+
<td><code>@modelcontextprotocol/server-filesystem /</code></td>
|
|
335
|
+
<td><code>/</code></td>
|
|
336
|
+
<td>-</td>
|
|
337
|
+
<td><code>GITHUB_TOKEN=ghp...890 (32 chars)</code></td>
|
|
338
|
+
<td>-</td>
|
|
339
|
+
</tr><tr>
|
|
340
|
+
<td><strong>shell-installer</strong><br><code>site/e2e/claude_desktop_config.json</code></td>
|
|
341
|
+
<td><code>bash</code></td>
|
|
342
|
+
<td><code>-c curl https://example.com/install.sh | bash</code></td>
|
|
343
|
+
<td>-</td>
|
|
344
|
+
<td>-</td>
|
|
345
|
+
<td>-</td>
|
|
346
|
+
<td>-</td>
|
|
347
|
+
</tr><tr>
|
|
348
|
+
<td><strong>remote-prod</strong><br><code>site/e2e/claude_desktop_config.json</code></td>
|
|
349
|
+
<td>-</td>
|
|
350
|
+
<td>-</td>
|
|
351
|
+
<td>-</td>
|
|
352
|
+
<td><code>https://mcp.example.com/sse</code></td>
|
|
353
|
+
<td>-</td>
|
|
354
|
+
<td><code>Authorization=Bea...ken (27 chars)</code></td>
|
|
355
|
+
</tr></tbody>
|
|
356
|
+
</table></div>
|
|
357
|
+
</section>
|
|
358
|
+
|
|
359
|
+
<section>
|
|
360
|
+
<h2>Findings</h2>
|
|
361
|
+
<div class="table-wrap"><table>
|
|
362
|
+
<thead><tr><th>Severity</th><th>Rule</th><th>Server</th><th>Finding</th><th>Evidence</th><th>Recommendation</th></tr></thead>
|
|
363
|
+
<tbody><tr>
|
|
364
|
+
<td><span class="pill critical">critical</span></td>
|
|
365
|
+
<td><code>MCP010</code></td>
|
|
366
|
+
<td>shell-installer</td>
|
|
367
|
+
<td>Shell command executes inline script</td>
|
|
368
|
+
<td><code>command=bash args=-c curl https://example.com/install.sh | bash</code></td>
|
|
369
|
+
<td>Use a direct, pinned executable instead of a shell wrapper. If a shell is required, place the script in source control and review it.</td>
|
|
370
|
+
</tr><tr>
|
|
371
|
+
<td><span class="pill critical">critical</span></td>
|
|
372
|
+
<td><code>MCP050</code></td>
|
|
373
|
+
<td>shell-installer</td>
|
|
374
|
+
<td>MCP server command includes a dangerous operation</td>
|
|
375
|
+
<td><code>curl pipe to shell</code></td>
|
|
376
|
+
<td>Remove the dangerous operation from MCP startup. Run destructive setup steps manually and review them separately.</td>
|
|
377
|
+
</tr><tr>
|
|
378
|
+
<td><span class="pill high">high</span></td>
|
|
379
|
+
<td><code>MCP021</code></td>
|
|
380
|
+
<td>filesystem-all-home</td>
|
|
381
|
+
<td>Remote MCP package is not version pinned</td>
|
|
382
|
+
<td><code>package=@modelcontextprotocol/server-filesystem</code></td>
|
|
383
|
+
<td>Pin the package to an exact version such as package@1.2.3 and review updates before changing it.</td>
|
|
384
|
+
</tr><tr>
|
|
385
|
+
<td><span class="pill high">high</span></td>
|
|
386
|
+
<td><code>MCP030</code></td>
|
|
387
|
+
<td>filesystem-all-home</td>
|
|
388
|
+
<td>Secret-like environment variable is exposed to MCP server</td>
|
|
389
|
+
<td><code>GITHUB_TOKEN=ghp...890 (32 chars)</code></td>
|
|
390
|
+
<td>Pass the least privileged token possible. Prefer scoped tokens, short-lived credentials, and a dedicated service account.</td>
|
|
391
|
+
</tr><tr>
|
|
392
|
+
<td><span class="pill high">high</span></td>
|
|
393
|
+
<td><code>MCP040</code></td>
|
|
394
|
+
<td>filesystem-all-home</td>
|
|
395
|
+
<td>MCP server has a broad working directory</td>
|
|
396
|
+
<td><code>cwd=/</code></td>
|
|
397
|
+
<td>Run the server in a narrow project directory or sandbox with only the files it needs.</td>
|
|
398
|
+
</tr><tr>
|
|
399
|
+
<td><span class="pill high">high</span></td>
|
|
400
|
+
<td><code>MCP041</code></td>
|
|
401
|
+
<td>filesystem-all-home</td>
|
|
402
|
+
<td>MCP server argument grants broad filesystem access</td>
|
|
403
|
+
<td><code>arg=/</code></td>
|
|
404
|
+
<td>Replace broad filesystem paths with a dedicated project folder or read-only sandbox path.</td>
|
|
405
|
+
</tr><tr>
|
|
406
|
+
<td><span class="pill high">high</span></td>
|
|
407
|
+
<td><code>MCP061</code></td>
|
|
408
|
+
<td>remote-prod</td>
|
|
409
|
+
<td>Secret-like header is configured for remote MCP server</td>
|
|
410
|
+
<td><code>Authorization=Bea...ken (27 chars)</code></td>
|
|
411
|
+
<td>Use scoped, short-lived credentials and avoid placing long-lived secrets directly in MCP config files.</td>
|
|
412
|
+
</tr><tr>
|
|
413
|
+
<td><span class="pill medium">medium</span></td>
|
|
414
|
+
<td><code>MCP020</code></td>
|
|
415
|
+
<td>filesystem-all-home</td>
|
|
416
|
+
<td>MCP server is launched through a remote package runner</td>
|
|
417
|
+
<td><code>command=npx package=@modelcontextprotocol/server-filesystem</code></td>
|
|
418
|
+
<td>Pin the package version, review the package source, and prefer a local lockfile or vendored executable for sensitive tools.</td>
|
|
419
|
+
</tr><tr>
|
|
420
|
+
<td><span class="pill medium">medium</span></td>
|
|
421
|
+
<td><code>MCP060</code></td>
|
|
422
|
+
<td>remote-prod</td>
|
|
423
|
+
<td>Remote MCP server URL is configured</td>
|
|
424
|
+
<td><code>url=https://mcp.example.com/sse</code></td>
|
|
425
|
+
<td>Verify the provider, use HTTPS, document the data sent to this server, and keep an allowlist of approved remote endpoints.</td>
|
|
426
|
+
</tr></tbody>
|
|
427
|
+
</table></div>
|
|
428
|
+
</section>
|
|
429
|
+
|
|
430
|
+
<section class="notes">
|
|
431
|
+
<h2>Review Notes</h2>
|
|
432
|
+
<ul>
|
|
433
|
+
<li>Secret-like values are redacted before rendering this report.</li>
|
|
434
|
+
<li>Review each server before granting access to files, shells, SaaS accounts, or production systems.</li>
|
|
435
|
+
<li>This report assists security review and does not guarantee that every issue was found.</li>
|
|
436
|
+
</ul>
|
|
437
|
+
</section>
|
|
438
|
+
</main>
|
|
439
|
+
</body>
|
|
440
|
+
</html>
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
{
|
|
2
|
+
"metadata": {
|
|
3
|
+
"generatedAt": "2026-05-10T09:16:08.688Z",
|
|
4
|
+
"cwd": ".",
|
|
5
|
+
"home": "~",
|
|
6
|
+
"toolVersion": "0.3.1"
|
|
7
|
+
},
|
|
8
|
+
"scannedFiles": [
|
|
9
|
+
"site/e2e/claude_desktop_config.json"
|
|
10
|
+
],
|
|
11
|
+
"servers": [
|
|
12
|
+
{
|
|
13
|
+
"name": "filesystem-all-home",
|
|
14
|
+
"configPath": "site/e2e/claude_desktop_config.json",
|
|
15
|
+
"command": "npx",
|
|
16
|
+
"args": [
|
|
17
|
+
"@modelcontextprotocol/server-filesystem",
|
|
18
|
+
"/"
|
|
19
|
+
],
|
|
20
|
+
"env": {
|
|
21
|
+
"GITHUB_TOKEN": "ghp...890 (32 chars)"
|
|
22
|
+
},
|
|
23
|
+
"cwd": "/",
|
|
24
|
+
"url": "",
|
|
25
|
+
"headers": {}
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"name": "shell-installer",
|
|
29
|
+
"configPath": "site/e2e/claude_desktop_config.json",
|
|
30
|
+
"command": "bash",
|
|
31
|
+
"args": [
|
|
32
|
+
"-c",
|
|
33
|
+
"curl https://example.com/install.sh | bash"
|
|
34
|
+
],
|
|
35
|
+
"env": {},
|
|
36
|
+
"cwd": "",
|
|
37
|
+
"url": "",
|
|
38
|
+
"headers": {}
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"name": "remote-prod",
|
|
42
|
+
"configPath": "site/e2e/claude_desktop_config.json",
|
|
43
|
+
"command": "",
|
|
44
|
+
"args": [],
|
|
45
|
+
"env": {},
|
|
46
|
+
"cwd": "",
|
|
47
|
+
"url": "https://mcp.example.com/sse",
|
|
48
|
+
"headers": {
|
|
49
|
+
"Authorization": "Bea...ken (27 chars)"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
],
|
|
53
|
+
"findings": [
|
|
54
|
+
{
|
|
55
|
+
"id": "MCP010",
|
|
56
|
+
"severity": "critical",
|
|
57
|
+
"title": "Shell command executes inline script",
|
|
58
|
+
"serverName": "shell-installer",
|
|
59
|
+
"configPath": "site/e2e/claude_desktop_config.json",
|
|
60
|
+
"evidence": "command=bash args=-c curl https://example.com/install.sh | bash",
|
|
61
|
+
"recommendation": "Use a direct, pinned executable instead of a shell wrapper. If a shell is required, place the script in source control and review it."
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"id": "MCP050",
|
|
65
|
+
"severity": "critical",
|
|
66
|
+
"title": "MCP server command includes a dangerous operation",
|
|
67
|
+
"serverName": "shell-installer",
|
|
68
|
+
"configPath": "site/e2e/claude_desktop_config.json",
|
|
69
|
+
"evidence": "curl pipe to shell",
|
|
70
|
+
"recommendation": "Remove the dangerous operation from MCP startup. Run destructive setup steps manually and review them separately."
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"id": "MCP021",
|
|
74
|
+
"severity": "high",
|
|
75
|
+
"title": "Remote MCP package is not version pinned",
|
|
76
|
+
"serverName": "filesystem-all-home",
|
|
77
|
+
"configPath": "site/e2e/claude_desktop_config.json",
|
|
78
|
+
"evidence": "package=@modelcontextprotocol/server-filesystem",
|
|
79
|
+
"recommendation": "Pin the package to an exact version such as package@1.2.3 and review updates before changing it."
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"id": "MCP030",
|
|
83
|
+
"severity": "high",
|
|
84
|
+
"title": "Secret-like environment variable is exposed to MCP server",
|
|
85
|
+
"serverName": "filesystem-all-home",
|
|
86
|
+
"configPath": "site/e2e/claude_desktop_config.json",
|
|
87
|
+
"evidence": "GITHUB_TOKEN=ghp...890 (32 chars)",
|
|
88
|
+
"recommendation": "Pass the least privileged token possible. Prefer scoped tokens, short-lived credentials, and a dedicated service account."
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"id": "MCP040",
|
|
92
|
+
"severity": "high",
|
|
93
|
+
"title": "MCP server has a broad working directory",
|
|
94
|
+
"serverName": "filesystem-all-home",
|
|
95
|
+
"configPath": "site/e2e/claude_desktop_config.json",
|
|
96
|
+
"evidence": "cwd=/",
|
|
97
|
+
"recommendation": "Run the server in a narrow project directory or sandbox with only the files it needs."
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"id": "MCP041",
|
|
101
|
+
"severity": "high",
|
|
102
|
+
"title": "MCP server argument grants broad filesystem access",
|
|
103
|
+
"serverName": "filesystem-all-home",
|
|
104
|
+
"configPath": "site/e2e/claude_desktop_config.json",
|
|
105
|
+
"evidence": "arg=/",
|
|
106
|
+
"recommendation": "Replace broad filesystem paths with a dedicated project folder or read-only sandbox path."
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"id": "MCP061",
|
|
110
|
+
"severity": "high",
|
|
111
|
+
"title": "Secret-like header is configured for remote MCP server",
|
|
112
|
+
"serverName": "remote-prod",
|
|
113
|
+
"configPath": "site/e2e/claude_desktop_config.json",
|
|
114
|
+
"evidence": "Authorization=Bea...ken (27 chars)",
|
|
115
|
+
"recommendation": "Use scoped, short-lived credentials and avoid placing long-lived secrets directly in MCP config files."
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
"id": "MCP020",
|
|
119
|
+
"severity": "medium",
|
|
120
|
+
"title": "MCP server is launched through a remote package runner",
|
|
121
|
+
"serverName": "filesystem-all-home",
|
|
122
|
+
"configPath": "site/e2e/claude_desktop_config.json",
|
|
123
|
+
"evidence": "command=npx package=@modelcontextprotocol/server-filesystem",
|
|
124
|
+
"recommendation": "Pin the package version, review the package source, and prefer a local lockfile or vendored executable for sensitive tools."
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
"id": "MCP060",
|
|
128
|
+
"severity": "medium",
|
|
129
|
+
"title": "Remote MCP server URL is configured",
|
|
130
|
+
"serverName": "remote-prod",
|
|
131
|
+
"configPath": "site/e2e/claude_desktop_config.json",
|
|
132
|
+
"evidence": "url=https://mcp.example.com/sse",
|
|
133
|
+
"recommendation": "Verify the provider, use HTTPS, document the data sent to this server, and keep an allowlist of approved remote endpoints."
|
|
134
|
+
}
|
|
135
|
+
],
|
|
136
|
+
"summary": {
|
|
137
|
+
"scannedFileCount": 1,
|
|
138
|
+
"serverCount": 3,
|
|
139
|
+
"findingCount": 9,
|
|
140
|
+
"counts": {
|
|
141
|
+
"critical": 2,
|
|
142
|
+
"high": 5,
|
|
143
|
+
"medium": 2,
|
|
144
|
+
"low": 0
|
|
145
|
+
},
|
|
146
|
+
"riskScore": 98
|
|
147
|
+
}
|
|
148
|
+
}
|