@mcp-guardian/server 1.0.1 → 1.3.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.
@@ -7,6 +7,7 @@ import { HistoryDatabase } from '../database/history-db.js';
7
7
  import { OAuthValidator } from '../auth/oauth.js';
8
8
  import { SessionCache } from '../auth/session-cache.js';
9
9
  import { CircuitBreaker } from '../utils/circuit-breaker.js';
10
+ import { createMtlsAgent } from '../utils/mtls-config.js';
10
11
  import * as Metrics from '../utils/metrics.js';
11
12
  import { Logger } from '../utils/logger.js';
12
13
  /**
@@ -24,7 +25,8 @@ export class HttpProxyServer {
24
25
  db;
25
26
  port;
26
27
  server = null;
27
- constructor(targetUrl, serverName, policyEngine, authValidator, db, port = 4000) {
28
+ httpsAgent;
29
+ constructor(targetUrl, serverName, policyEngine, authValidator, db, port = 4000, mtlsConfig) {
28
30
  this.serverName = serverName;
29
31
  this.targetUrl = targetUrl.replace(/\/$/, '');
30
32
  this.policyEngine = policyEngine || null;
@@ -34,7 +36,11 @@ export class HttpProxyServer {
34
36
  this.tokenCounter = new TokenCounter();
35
37
  this.db = db || new HistoryDatabase(':memory:');
36
38
  this.port = port;
39
+ this.httpsAgent = createMtlsAgent(mtlsConfig || { enabled: false, rejectUnauthorized: true });
37
40
  Metrics.circuitBreakerState.set({ server_name: this.serverName }, 0);
41
+ if (this.httpsAgent) {
42
+ Logger.info(`[http-proxy:${this.serverName}] mTLS enabled for upstream connection`);
43
+ }
38
44
  }
39
45
  async start() {
40
46
  this.server = createServer((req, res) => this.handleRequest(req, res));
@@ -118,13 +124,18 @@ export class HttpProxyServer {
118
124
  try {
119
125
  const upstreamUrl = new URL(this.targetUrl + (req.url || '/'));
120
126
  const isHttps = upstreamUrl.protocol === 'https:';
121
- const proxyReq = (isHttps ? httpsReq : httpReq)({
127
+ const reqOpts = {
122
128
  hostname: upstreamUrl.hostname,
123
129
  port: upstreamUrl.port || (isHttps ? 443 : 80),
124
130
  path: upstreamUrl.pathname + upstreamUrl.search,
125
131
  method: req.method,
126
132
  headers: { ...req.headers, host: upstreamUrl.hostname },
127
- }, (upstreamRes) => {
133
+ };
134
+ // Attach mTLS agent for HTTPS connections
135
+ if (isHttps && this.httpsAgent) {
136
+ reqOpts.agent = this.httpsAgent;
137
+ }
138
+ const proxyReq = (isHttps ? httpsReq : httpReq)(reqOpts, (upstreamRes) => {
128
139
  res.writeHead(upstreamRes.statusCode || 200, upstreamRes.headers);
129
140
  upstreamRes.pipe(res);
130
141
  this.circuitBreaker.recordSuccess();
@@ -1 +1 @@
1
- {"version":3,"file":"http-proxy-server.js","sourceRoot":"","sources":["../../src/proxy/http-proxy-server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"http-proxy-server.js","sourceRoot":"","sources":["../../src/proxy/http-proxy-server.ts"],"names":[],"mappings":"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"}
@@ -1,10 +1,19 @@
1
+ import { createServer } from 'http';
1
2
  import { PolicyWatcher } from '../policy/policy-watcher.js';
3
+ import { DashboardAuth } from '../auth/dashboard-auth.js';
2
4
  /**
3
5
  * Lightweight dashboard server that serves:
4
- * - / — the dashboard HTML
5
- * - /api/policycurrent policy (JSON)
6
- * - /api/policy/reloadtrigger policy reload
7
- * - /metricsPrometheus metrics
6
+ * - / — the dashboard HTML (requires auth if enabled)
7
+ * - /loginlogin page (when JWT auth is enabled)
8
+ * - /api/loginPOST login endpoint
9
+ * - /api/policycurrent policy (JSON, requires auth)
10
+ * - /api/policy/reload — trigger policy reload (requires auth)
11
+ * - /metrics — Prometheus metrics (can be auth-gated or public via DASHBOARD_METRICS_PUBLIC=true)
12
+ *
13
+ * v1.2: Integrated DashboardAuth for JWT/API key authentication, CSRF protection.
8
14
  */
9
- export declare function startDashboardServer(port?: number, policyWatcher?: PolicyWatcher): Promise<void>;
15
+ export declare function startDashboardServer(port?: number, policyWatcher?: PolicyWatcher, dashboardAuth?: DashboardAuth): Promise<{
16
+ auth: DashboardAuth;
17
+ server: ReturnType<typeof createServer>;
18
+ }>;
10
19
  //# sourceMappingURL=dashboard-server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dashboard-server.d.ts","sourceRoot":"","sources":["../../src/utils/dashboard-server.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAM5D;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,GAAE,MAAa,EACnB,aAAa,CAAC,EAAE,aAAa,GAC5B,OAAO,CAAC,IAAI,CAAC,CA2Ef"}
1
+ {"version":3,"file":"dashboard-server.d.ts","sourceRoot":"","sources":["../../src/utils/dashboard-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAmC,MAAM,MAAM,CAAC;AAKrE,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAM1D;;;;;;;;;;GAUG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,GAAE,MAAa,EACnB,aAAa,CAAC,EAAE,aAAa,EAC7B,aAAa,CAAC,EAAE,aAAa,GAC5B,OAAO,CAAC;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAA;CAAE,CAAC,CA2P3E"}
@@ -3,84 +3,256 @@ import { readFileSync } from 'fs';
3
3
  import { resolve, dirname } from 'path';
4
4
  import { fileURLToPath } from 'url';
5
5
  import { Logger } from './logger.js';
6
+ import { DashboardAuth } from '../auth/dashboard-auth.js';
6
7
  const __filename = fileURLToPath(import.meta.url);
7
8
  const __dirname = dirname(__filename);
8
9
  /**
9
10
  * Lightweight dashboard server that serves:
10
- * - / — the dashboard HTML
11
- * - /api/policycurrent policy (JSON)
12
- * - /api/policy/reloadtrigger policy reload
13
- * - /metricsPrometheus metrics
11
+ * - / — the dashboard HTML (requires auth if enabled)
12
+ * - /loginlogin page (when JWT auth is enabled)
13
+ * - /api/loginPOST login endpoint
14
+ * - /api/policycurrent policy (JSON, requires auth)
15
+ * - /api/policy/reload — trigger policy reload (requires auth)
16
+ * - /metrics — Prometheus metrics (can be auth-gated or public via DASHBOARD_METRICS_PUBLIC=true)
17
+ *
18
+ * v1.2: Integrated DashboardAuth for JWT/API key authentication, CSRF protection.
14
19
  */
15
- export async function startDashboardServer(port = 4000, policyWatcher) {
20
+ export async function startDashboardServer(port = 4000, policyWatcher, dashboardAuth) {
16
21
  if (process.env['DASHBOARD_ENABLED'] !== 'true') {
17
22
  Logger.debug('[dashboard] Dashboard server not enabled (set DASHBOARD_ENABLED=true)');
18
- return;
23
+ return { auth: dashboardAuth || new DashboardAuth({ enabled: false }), server: createServer((_req, res) => {
24
+ res.writeHead(200);
25
+ res.end();
26
+ }) };
27
+ }
28
+ const auth = dashboardAuth || new DashboardAuth();
29
+ const authEnabled = auth.isEnabled();
30
+ if (authEnabled) {
31
+ Logger.info('[dashboard] Dashboard authentication enabled');
32
+ }
33
+ else {
34
+ Logger.info('[dashboard] Dashboard running without authentication (set DASHBOARD_AUTH_ENABLED=true)');
19
35
  }
20
36
  const dashboardHtml = readFileSync(resolve(__dirname, '..', '..', 'deploy', 'dashboard.html'), 'utf-8');
37
+ /** Read JSON body from request */
38
+ async function readBody(req) {
39
+ return new Promise((resolve, reject) => {
40
+ let data = '';
41
+ req.on('data', (chunk) => { data += chunk.toString(); });
42
+ req.on('end', () => {
43
+ try {
44
+ resolve(data ? JSON.parse(data) : {});
45
+ }
46
+ catch {
47
+ resolve({});
48
+ }
49
+ });
50
+ req.on('error', reject);
51
+ });
52
+ }
53
+ /** Parse form-encoded body from request */
54
+ async function readFormBody(req) {
55
+ return new Promise((resolve) => {
56
+ let data = '';
57
+ req.on('data', (chunk) => { data += chunk.toString(); });
58
+ req.on('end', () => {
59
+ const result = {};
60
+ if (data) {
61
+ try {
62
+ const params = new URLSearchParams(data);
63
+ for (const [key, value] of params) {
64
+ result[key] = value;
65
+ }
66
+ }
67
+ catch {
68
+ // Ignore parse errors
69
+ }
70
+ }
71
+ resolve(result);
72
+ });
73
+ });
74
+ }
75
+ /** Get client IP for rate limiting */
76
+ function getClientIp(req) {
77
+ const forwarded = req.headers['x-forwarded-for'];
78
+ if (forwarded) {
79
+ const first = Array.isArray(forwarded) ? forwarded[0] : forwarded.split(',')[0];
80
+ return (first || '').trim();
81
+ }
82
+ return req.socket?.remoteAddress || 'unknown';
83
+ }
84
+ /** Write JSON response */
85
+ function writeJson(res, status, data) {
86
+ res.writeHead(status, { 'Content-Type': 'application/json' });
87
+ res.end(JSON.stringify(data));
88
+ }
21
89
  const server = createServer(async (req, res) => {
22
90
  const url = req.url || '/';
91
+ const method = req.method || 'GET';
92
+ // ── CORS preflight ─────────────────────────────────────
93
+ if (method === 'OPTIONS') {
94
+ res.writeHead(204, {
95
+ 'Access-Control-Allow-Origin': '*',
96
+ 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
97
+ 'Access-Control-Allow-Headers': 'Content-Type, Authorization, X-API-Key',
98
+ });
99
+ res.end();
100
+ return;
101
+ }
102
+ // ── CORS headers on all responses ─────────────────────
103
+ const setCors = () => {
104
+ res.setHeader('Access-Control-Allow-Origin', '*');
105
+ };
23
106
  try {
24
- // ── Dashboard HTML ──────────────────────────────────────
107
+ // ── Login page (only when JWT auth is enabled, no API key set) ──
108
+ if (url === '/login' && method === 'GET') {
109
+ setCors();
110
+ if (auth.isEnabled() && auth.hasJwtSessionAuth()) {
111
+ res.writeHead(200, { 'Content-Type': 'text/html' });
112
+ res.end(auth.getLoginPageHtml());
113
+ }
114
+ else {
115
+ res.writeHead(302, { 'Location': '/' });
116
+ res.end();
117
+ }
118
+ return;
119
+ }
120
+ // ── Login API endpoint ──────────────────────────────
121
+ if (url === '/api/login' && method === 'POST') {
122
+ setCors();
123
+ const ip = getClientIp(req);
124
+ const contentType = req.headers['content-type'] || '';
125
+ let body;
126
+ if (contentType.includes('application/x-www-form-urlencoded')) {
127
+ body = await readFormBody(req);
128
+ }
129
+ else {
130
+ body = await readBody(req);
131
+ }
132
+ const result = auth.login({
133
+ url,
134
+ headers: req.headers,
135
+ body: {
136
+ username: body.username,
137
+ password: body.password,
138
+ api_key: body.api_key,
139
+ },
140
+ ip,
141
+ });
142
+ if (result.success && req.headers['content-type']?.includes('form')) {
143
+ // Form submission — redirect to dashboard with token
144
+ res.writeHead(302, {
145
+ 'Location': `/?api_key=${encodeURIComponent(result.token)}`,
146
+ 'Set-Cookie': `mcp_guardian_session=${result.token}; Path=/; HttpOnly; SameSite=Strict; Max-Age=3600`,
147
+ });
148
+ res.end();
149
+ return;
150
+ }
151
+ if (result.success) {
152
+ writeJson(res, 200, { success: true, token: result.token });
153
+ }
154
+ else {
155
+ writeJson(res, 401, { success: false, error: result.error });
156
+ }
157
+ return;
158
+ }
159
+ // ── Auth check for all other routes ─────────────────
160
+ const authResult = auth.authenticate({ url, headers: req.headers, method });
161
+ if (!authResult.authenticated) {
162
+ setCors();
163
+ if (req.headers['accept']?.includes('text/html')) {
164
+ // Browser request — redirect to login
165
+ res.writeHead(302, { 'Location': '/login' });
166
+ res.end();
167
+ }
168
+ else {
169
+ writeJson(res, 401, { error: 'Authentication required', reason: authResult.reason });
170
+ }
171
+ return;
172
+ }
173
+ // ── Dashboard HTML ──────────────────────────────────
25
174
  if (url === '/' || url === '/dashboard.html') {
175
+ setCors();
26
176
  res.writeHead(200, { 'Content-Type': 'text/html' });
27
177
  res.end(dashboardHtml);
28
178
  return;
29
179
  }
30
- // ── Policy API ──────────────────────────────────────────
31
- if (url === '/api/policy' && req.method === 'GET') {
180
+ // ── Policy API ──────────────────────────────────────
181
+ if (url === '/api/policy' && method === 'GET') {
182
+ setCors();
32
183
  if (!policyWatcher || !policyWatcher.get()) {
33
- res.writeHead(404, { 'Content-Type': 'application/json' });
34
- res.end(JSON.stringify({ error: 'No active policy. Start proxy with --policy flag.' }));
184
+ writeJson(res, 404, { error: 'No active policy. Start proxy with --policy flag.' });
35
185
  return;
36
186
  }
37
- res.writeHead(200, { 'Content-Type': 'application/json' });
38
- res.end(JSON.stringify({ mode: policyWatcher.get().getMode(), rules: 'Policy engine active (YAML view available on filesystem)' }));
187
+ writeJson(res, 200, { mode: policyWatcher.get().getMode(), rules: 'Policy engine active (YAML view available on filesystem)' });
39
188
  return;
40
189
  }
41
- if (url === '/api/policy/reload' && req.method === 'POST') {
190
+ if (url === '/api/policy/reload' && method === 'POST') {
191
+ setCors();
42
192
  if (!policyWatcher) {
43
- res.writeHead(404, { 'Content-Type': 'application/json' });
44
- res.end(JSON.stringify({ error: 'Policy watcher not configured' }));
193
+ writeJson(res, 404, { error: 'Policy watcher not configured' });
45
194
  return;
46
195
  }
47
- // PolicyWatcher auto-reloads via chokidar no manual reload needed
48
- res.writeHead(200, { 'Content-Type': 'application/json' });
49
- res.end(JSON.stringify({ status: 'ok', message: 'Policy watcher is active. File changes are auto-detected.' }));
196
+ writeJson(res, 200, { status: 'ok', message: 'Policy watcher is active. File changes are auto-detected.' });
50
197
  return;
51
198
  }
52
- // ── Prometheus /metrics proxy ──────────────────────────
199
+ // ── Prometheus /metrics proxy ──────────────────────
53
200
  if (url === '/metrics') {
54
- try {
55
- // Fetch from the metrics server (port 9090 by default)
56
- const metricsPort = process.env['METRICS_PORT'] || '9090';
57
- const metricsRes = await fetch(`http://localhost:${metricsPort}/metrics`);
58
- if (!metricsRes.ok)
59
- throw new Error(`Metrics server returned ${metricsRes.status}`);
60
- const text = await metricsRes.text();
61
- res.writeHead(200, {
62
- 'Content-Type': 'text/plain; version=0.0.4; charset=utf-8',
63
- 'Access-Control-Allow-Origin': '*',
64
- });
65
- res.end(text);
201
+ setCors();
202
+ const metricsPublic = process.env['DASHBOARD_METRICS_PUBLIC'] === 'true';
203
+ // Re-check auth for metrics unless public
204
+ if (metricsPublic || authResult.authenticated) {
205
+ try {
206
+ const metricsPort = process.env['METRICS_PORT'] || '9090';
207
+ const metricsRes = await fetch(`http://localhost:${metricsPort}/metrics`);
208
+ if (!metricsRes.ok)
209
+ throw new Error(`Metrics server returned ${metricsRes.status}`);
210
+ const text = await metricsRes.text();
211
+ res.writeHead(200, {
212
+ 'Content-Type': 'text/plain; version=0.0.4; charset=utf-8',
213
+ 'Access-Control-Allow-Origin': '*',
214
+ });
215
+ res.end(text);
216
+ }
217
+ catch {
218
+ writeJson(res, 200, { error: 'Metrics not available. Ensure METRICS_ENABLED=true and proxy is running.' });
219
+ }
66
220
  }
67
- catch {
68
- res.writeHead(200, { 'Content-Type': 'application/json' });
69
- res.end(JSON.stringify({ error: 'Metrics not available. Ensure METRICS_ENABLED=true and proxy is running.' }));
221
+ else {
222
+ writeJson(res, 401, { error: 'Authentication required for metrics' });
223
+ }
224
+ return;
225
+ }
226
+ // ── Auth status check ───────────────────────────────
227
+ if (url === '/api/auth/status' && method === 'GET') {
228
+ setCors();
229
+ writeJson(res, 200, { authenticated: true, identity: authResult.identity, authEnabled });
230
+ return;
231
+ }
232
+ // ── Logout ──────────────────────────────────────────
233
+ if (url === '/api/logout' && method === 'POST') {
234
+ setCors();
235
+ const authHeader = req.headers['authorization'];
236
+ if (authHeader) {
237
+ const match = authHeader.match(/^Bearer\s+(.+)$/i);
238
+ if (match)
239
+ auth.logout(match[1]);
70
240
  }
241
+ writeJson(res, 200, { status: 'ok', message: 'Logged out' });
71
242
  return;
72
243
  }
73
- // ── 404 ─────────────────────────────────────────────────
74
- res.writeHead(404, { 'Content-Type': 'application/json' });
75
- res.end(JSON.stringify({ error: 'Not found' }));
244
+ // ── 404 ──────────────────────────────────────────────
245
+ setCors();
246
+ writeJson(res, 404, { error: 'Not found' });
76
247
  }
77
248
  catch (err) {
78
- res.writeHead(500, { 'Content-Type': 'application/json' });
79
- res.end(JSON.stringify({ error: err?.message || 'Internal error' }));
249
+ setCors();
250
+ writeJson(res, 500, { error: err?.message || 'Internal error' });
80
251
  }
81
252
  });
82
253
  server.listen(port, () => {
83
- Logger.info(`[dashboard] Dashboard available at http://localhost:${port}`);
254
+ Logger.info(`[dashboard] Dashboard available at http://localhost:${port}${authEnabled ? ' (auth enabled)' : ''}`);
84
255
  });
256
+ return { auth, server };
85
257
  }
86
258
  //# sourceMappingURL=dashboard-server.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"dashboard-server.js","sourceRoot":"","sources":["../../src/utils/dashboard-server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dashboard-server.js","sourceRoot":"","sources":["../../src/utils/dashboard-server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import { Agent as HttpsAgent } from 'https';
2
+ export interface MtlsConfig {
3
+ enabled: boolean;
4
+ ca?: Buffer;
5
+ cert?: Buffer;
6
+ key?: Buffer;
7
+ rejectUnauthorized: boolean;
8
+ }
9
+ /**
10
+ * Load mTLS configuration from environment variables.
11
+ */
12
+ export declare function loadMtlsConfig(): MtlsConfig;
13
+ /**
14
+ * Create an HTTPS Agent configured with mTLS client certificate and CA.
15
+ */
16
+ export declare function createMtlsAgent(config: MtlsConfig): HttpsAgent | undefined;
17
+ /**
18
+ * CLI flag names for mTLS configuration.
19
+ */
20
+ export declare const MTL_CLI_FLAGS: {
21
+ readonly tlsEnabled: "--mtls";
22
+ readonly tlsCa: "--mtls-ca <path>";
23
+ readonly tlsCert: "--mtls-cert <path>";
24
+ readonly tlsKey: "--mtls-key <path>";
25
+ readonly tlsInsecure: "--mtls-insecure";
26
+ };
27
+ //# sourceMappingURL=mtls-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mtls-config.d.ts","sourceRoot":"","sources":["../../src/utils/mtls-config.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,KAAK,IAAI,UAAU,EAAE,MAAM,OAAO,CAAC;AAG5C,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,kBAAkB,EAAE,OAAO,CAAC;CAC7B;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,UAAU,CAsC3C;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG,UAAU,GAAG,SAAS,CAW1E;AAED;;GAEG;AACH,eAAO,MAAM,aAAa;;;;;;CAMhB,CAAC"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * mTLS Configuration for Zero-Trust Proxy ↔ Upstream Communication.
3
+ *
4
+ * When MCP_TLS_ENABLED=true, the HTTP/SSE proxy validates the upstream
5
+ * server's certificate AND presents a client certificate for mutual
6
+ * authentication. This prevents MITM attacks and ensures only authorized
7
+ * proxies can connect to upstream MCP servers.
8
+ *
9
+ * Configuration via environment variables:
10
+ * MCP_TLS_ENABLED=true|false
11
+ * MCP_TLS_CA=/path/to/ca-cert.pem (required — trusted CA bundle)
12
+ * MCP_TLS_CERT=/path/to/client-cert.pem (required — proxy's client cert)
13
+ * MCP_TLS_KEY=/path/to/client-key.pem (required — proxy's client key)
14
+ * MCP_TLS_REJECT_UNAUTHORIZED=true|false (default: true — strict mode)
15
+ */
16
+ import { readFileSync } from 'fs';
17
+ import { Agent as HttpsAgent } from 'https';
18
+ import { Logger } from './logger.js';
19
+ /**
20
+ * Load mTLS configuration from environment variables.
21
+ */
22
+ export function loadMtlsConfig() {
23
+ const enabled = process.env['MCP_TLS_ENABLED'] === 'true';
24
+ if (!enabled) {
25
+ return { enabled: false, rejectUnauthorized: true };
26
+ }
27
+ const caPath = process.env['MCP_TLS_CA'];
28
+ const certPath = process.env['MCP_TLS_CERT'];
29
+ const keyPath = process.env['MCP_TLS_KEY'];
30
+ const rejectUnauthorized = process.env['MCP_TLS_REJECT_UNAUTHORIZED'] !== 'false';
31
+ const missing = [];
32
+ if (!caPath)
33
+ missing.push('MCP_TLS_CA');
34
+ if (!certPath)
35
+ missing.push('MCP_TLS_CERT');
36
+ if (!keyPath)
37
+ missing.push('MCP_TLS_KEY');
38
+ if (missing.length > 0) {
39
+ Logger.error(`[mtls] mTLS enabled but missing env vars: ${missing.join(', ')}`);
40
+ throw new Error(`mTLS misconfigured: missing ${missing.join(', ')}`);
41
+ }
42
+ let ca;
43
+ let cert;
44
+ let key;
45
+ try {
46
+ ca = readFileSync(caPath);
47
+ cert = readFileSync(certPath);
48
+ key = readFileSync(keyPath);
49
+ }
50
+ catch (err) {
51
+ Logger.error(`[mtls] Failed to read TLS files: ${err?.message}`);
52
+ throw err;
53
+ }
54
+ Logger.info(`[mtls] mTLS enabled (CA: ${caPath}, cert: ${certPath}, rejectUnauthorized: ${rejectUnauthorized})`);
55
+ return { enabled: true, ca, cert, key, rejectUnauthorized };
56
+ }
57
+ /**
58
+ * Create an HTTPS Agent configured with mTLS client certificate and CA.
59
+ */
60
+ export function createMtlsAgent(config) {
61
+ if (!config.enabled)
62
+ return undefined;
63
+ return new HttpsAgent({
64
+ ca: config.ca,
65
+ cert: config.cert,
66
+ key: config.key,
67
+ rejectUnauthorized: config.rejectUnauthorized,
68
+ keepAlive: true,
69
+ keepAliveMsecs: 30000,
70
+ });
71
+ }
72
+ /**
73
+ * CLI flag names for mTLS configuration.
74
+ */
75
+ export const MTL_CLI_FLAGS = {
76
+ tlsEnabled: '--mtls',
77
+ tlsCa: '--mtls-ca <path>',
78
+ tlsCert: '--mtls-cert <path>',
79
+ tlsKey: '--mtls-key <path>',
80
+ tlsInsecure: '--mtls-insecure',
81
+ };
82
+ //# sourceMappingURL=mtls-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mtls-config.js","sourceRoot":"","sources":["../../src/utils/mtls-config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ export interface NormalizationResult {
2
+ /** The fully normalized string ready for policy evaluation */
3
+ normalized: string;
4
+ /** Whether any normalization was applied */
5
+ wasModified: boolean;
6
+ /** What transformations were applied */
7
+ transformations: string[];
8
+ /** The original raw input */
9
+ original: string;
10
+ }
11
+ /**
12
+ * PayloadNormalizer applies multi-stage normalization to defeat
13
+ * common evasion techniques targeting regex-based policy engines.
14
+ */
15
+ export declare class PayloadNormalizer {
16
+ private readonly maxDepth;
17
+ private readonly maxLength;
18
+ constructor(maxDepth?: number, maxLength?: number);
19
+ /**
20
+ * Full normalization pipeline for policy evaluation input.
21
+ */
22
+ normalize(input: string): NormalizationResult;
23
+ /**
24
+ * URL decode: %XX → character, handles malformed sequences.
25
+ */
26
+ private urlDecode;
27
+ /**
28
+ * Decode hex escapes: \x41 → 'A', \x00 → null byte detection.
29
+ */
30
+ private decodeHexEscapes;
31
+ /**
32
+ * Decode unicode escapes: \u0041 → 'A', \U00000041 → 'A'.
33
+ */
34
+ private decodeUnicodeEscapes;
35
+ /**
36
+ * Decode HTML entities: < -> <, &#60; -> <, &#x3C; -> <.
37
+ * Entity map built at runtime to avoid source-level entity decoding issues.
38
+ */
39
+ private static htmlEntityMap;
40
+ private static getHtmlEntityMap;
41
+ private decodeHtmlEntities;
42
+ /**
43
+ * Unwrap double escapes: \\. → literal character.
44
+ */
45
+ private unwrapDoubleEscapes;
46
+ /**
47
+ * Shell normalize: collapse common shell obfuscation patterns.
48
+ *
49
+ * - $'cmd' → cmd (ANSI-C quoting)
50
+ * - "c"m"d" → cmd (quote splitting)
51
+ * - ''cmd'' → cmd (empty quote pairs)
52
+ * - c\md → cmd (backslash escapes)
53
+ */
54
+ private shellNormalize;
55
+ /**
56
+ * Specifically normalize a JSON string value (tool argument).
57
+ * Handles nested JSON structures recursively.
58
+ */
59
+ normalizeJsonValue(value: unknown, depth?: number): unknown;
60
+ }
61
+ export declare function getNormalizer(): PayloadNormalizer;
62
+ //# sourceMappingURL=payload-normalizer.d.ts.map