@sonoma-security/mcp-gateway 0.1.2 → 0.1.5
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 +104 -45
- package/dist/__tests__/config.test.js +28 -0
- package/dist/__tests__/config.test.js.map +1 -1
- package/dist/__tests__/ssrf-protection.test.d.ts +2 -0
- package/dist/__tests__/ssrf-protection.test.d.ts.map +1 -0
- package/dist/__tests__/ssrf-protection.test.js +389 -0
- package/dist/__tests__/ssrf-protection.test.js.map +1 -0
- package/dist/auth/client.d.ts +2 -0
- package/dist/auth/client.d.ts.map +1 -1
- package/dist/auth/client.js +17 -15
- package/dist/auth/client.js.map +1 -1
- package/dist/auth/crypto.d.ts +23 -0
- package/dist/auth/crypto.d.ts.map +1 -0
- package/dist/auth/crypto.js +78 -0
- package/dist/auth/crypto.js.map +1 -0
- package/dist/auth/index.d.ts +4 -1
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +4 -1
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/server.d.ts +2 -0
- package/dist/auth/server.d.ts.map +1 -1
- package/dist/auth/server.js +337 -59
- package/dist/auth/server.js.map +1 -1
- package/dist/auth/storage.d.ts.map +1 -1
- package/dist/auth/storage.js +2 -72
- package/dist/auth/storage.js.map +1 -1
- package/dist/auth/upstream-oauth-provider.d.ts +41 -0
- package/dist/auth/upstream-oauth-provider.d.ts.map +1 -0
- package/dist/auth/upstream-oauth-provider.js +88 -0
- package/dist/auth/upstream-oauth-provider.js.map +1 -0
- package/dist/auth/upstream-oauth.d.ts +31 -0
- package/dist/auth/upstream-oauth.d.ts.map +1 -0
- package/dist/auth/upstream-oauth.js +79 -0
- package/dist/auth/upstream-oauth.js.map +1 -0
- package/dist/auth/upstream-token-store.d.ts +27 -0
- package/dist/auth/upstream-token-store.d.ts.map +1 -0
- package/dist/auth/upstream-token-store.js +103 -0
- package/dist/auth/upstream-token-store.js.map +1 -0
- package/dist/cli.js +115 -86
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +30 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +203 -9
- package/dist/config.js.map +1 -1
- package/dist/gateway.d.ts +23 -1
- package/dist/gateway.d.ts.map +1 -1
- package/dist/gateway.js +224 -35
- package/dist/gateway.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/pattern-matcher.d.ts +47 -0
- package/dist/pattern-matcher.d.ts.map +1 -0
- package/dist/pattern-matcher.js +98 -0
- package/dist/pattern-matcher.js.map +1 -0
- package/dist/sonoma-client.d.ts +21 -5
- package/dist/sonoma-client.d.ts.map +1 -1
- package/dist/sonoma-client.js +42 -2
- package/dist/sonoma-client.js.map +1 -1
- package/dist/ssrf-protection.d.ts +59 -0
- package/dist/ssrf-protection.d.ts.map +1 -0
- package/dist/ssrf-protection.js +253 -0
- package/dist/ssrf-protection.js.map +1 -0
- package/dist/types.d.ts +6 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/sonoma-client.d.ts
CHANGED
|
@@ -5,14 +5,17 @@
|
|
|
5
5
|
* Implements disk-backed queue for telemetry to prevent data loss.
|
|
6
6
|
*/
|
|
7
7
|
import type { ToolCallEvent } from "./types.js";
|
|
8
|
+
export interface PolicyRule {
|
|
9
|
+
identifier: string;
|
|
10
|
+
type: string;
|
|
11
|
+
status: "blocked" | "allowed" | "gateway";
|
|
12
|
+
toolPattern: string | null;
|
|
13
|
+
priority: number;
|
|
14
|
+
}
|
|
8
15
|
export interface PolicyResponse {
|
|
9
16
|
mode: "disabled" | "blocklist" | "allowlist";
|
|
10
17
|
gatewayAuthMode: "org_key" | "user_id";
|
|
11
|
-
list:
|
|
12
|
-
identifier: string;
|
|
13
|
-
type: string;
|
|
14
|
-
status: string;
|
|
15
|
-
}>;
|
|
18
|
+
list: PolicyRule[];
|
|
16
19
|
}
|
|
17
20
|
export declare class SonomaClient {
|
|
18
21
|
private endpoint;
|
|
@@ -70,5 +73,18 @@ export declare class SonomaClient {
|
|
|
70
73
|
* Fetch policy from Sonoma
|
|
71
74
|
*/
|
|
72
75
|
fetchPolicy(): Promise<PolicyResponse>;
|
|
76
|
+
/**
|
|
77
|
+
* Report discovered tools to Sonoma
|
|
78
|
+
* Called on gateway startup after connecting to upstream servers
|
|
79
|
+
*/
|
|
80
|
+
reportTools(servers: Array<{
|
|
81
|
+
serverIdentifier: string;
|
|
82
|
+
serverName: string;
|
|
83
|
+
tools: Array<{
|
|
84
|
+
name: string;
|
|
85
|
+
description?: string;
|
|
86
|
+
inputSchema?: Record<string, unknown>;
|
|
87
|
+
}>;
|
|
88
|
+
}>): Promise<void>;
|
|
73
89
|
}
|
|
74
90
|
//# sourceMappingURL=sonoma-client.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sonoma-client.d.ts","sourceRoot":"","sources":["../src/sonoma-client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"sonoma-client.d.ts","sourceRoot":"","sources":["../src/sonoma-client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAehD,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;IAC1C,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,UAAU,GAAG,WAAW,GAAG,WAAW,CAAC;IAC7C,eAAe,EAAE,SAAS,GAAG,SAAS,CAAC;IACvC,IAAI,EAAE,UAAU,EAAE,CAAC;CACpB;AAQD,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,aAAa,CAA+C;IACpE,OAAO,CAAC,KAAK,CAAU;gBAEX,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE;IAQ9E,OAAO,CAAC,GAAG;IAQX;;OAEG;YACW,QAAQ;IActB;;OAEG;IACH,mBAAmB,CAAC,UAAU,SAAQ,GAAG,IAAI;IAc7C;;OAEG;IACH,kBAAkB,IAAI,IAAI;IAO1B;;OAEG;IACH,OAAO,CAAC,eAAe;IAMvB;;OAEG;IACH,OAAO,CAAC,WAAW;IAqBnB;;OAEG;IACH,OAAO,CAAC,YAAY;IAkBpB;;OAEG;IACH,OAAO,CAAC,cAAc;IAMtB;;;OAGG;IACH,UAAU,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IAWtC;;;OAGG;IACG,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAsDrC;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,cAAc,CAAC;IAyB5C;;;OAGG;IACG,WAAW,CACf,OAAO,EAAE,KAAK,CAAC;QACb,gBAAgB,EAAE,MAAM,CAAC;QACzB,UAAU,EAAE,MAAM,CAAC;QACnB,KAAK,EAAE,KAAK,CAAC;YACX,IAAI,EAAE,MAAM,CAAC;YACb,WAAW,CAAC,EAAE,MAAM,CAAC;YACrB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;SACvC,CAAC,CAAC;KACJ,CAAC,GACD,OAAO,CAAC,IAAI,CAAC;CAqCjB"}
|
package/dist/sonoma-client.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Uses OAuth tokens from the auth module for authentication.
|
|
5
5
|
* Implements disk-backed queue for telemetry to prevent data loss.
|
|
6
6
|
*/
|
|
7
|
+
import { safeFetch } from "./ssrf-protection.js";
|
|
7
8
|
import { hostname, homedir } from "node:os";
|
|
8
9
|
import { join } from "node:path";
|
|
9
10
|
import { existsSync, appendFileSync, readFileSync, writeFileSync, statSync, unlinkSync, mkdirSync, } from "node:fs";
|
|
@@ -30,6 +31,8 @@ export class SonomaClient {
|
|
|
30
31
|
}
|
|
31
32
|
log(message, ...args) {
|
|
32
33
|
if (this.debug) {
|
|
34
|
+
// Security: message is from developer code, not user input
|
|
35
|
+
// nosemgrep: javascript.lang.security.audit.unsafe-formatstring.unsafe-formatstring
|
|
33
36
|
console.error(`[sonoma-client] ${message}`, ...args);
|
|
34
37
|
}
|
|
35
38
|
}
|
|
@@ -158,7 +161,7 @@ export class SonomaClient {
|
|
|
158
161
|
}
|
|
159
162
|
try {
|
|
160
163
|
const token = await this.getToken();
|
|
161
|
-
const response = await
|
|
164
|
+
const response = await safeFetch(`${this.endpoint}/api/mcp-visibility/telemetry`, {
|
|
162
165
|
method: "POST",
|
|
163
166
|
headers: {
|
|
164
167
|
"Content-Type": "application/json",
|
|
@@ -202,7 +205,7 @@ export class SonomaClient {
|
|
|
202
205
|
async fetchPolicy() {
|
|
203
206
|
try {
|
|
204
207
|
const token = await this.getToken();
|
|
205
|
-
const response = await
|
|
208
|
+
const response = await safeFetch(`${this.endpoint}/api/mcp-visibility/policy`, {
|
|
206
209
|
headers: {
|
|
207
210
|
Authorization: `Bearer ${token}`,
|
|
208
211
|
},
|
|
@@ -221,5 +224,42 @@ export class SonomaClient {
|
|
|
221
224
|
return { mode: "disabled", gatewayAuthMode: "org_key", list: [] };
|
|
222
225
|
}
|
|
223
226
|
}
|
|
227
|
+
/**
|
|
228
|
+
* Report discovered tools to Sonoma
|
|
229
|
+
* Called on gateway startup after connecting to upstream servers
|
|
230
|
+
*/
|
|
231
|
+
async reportTools(servers) {
|
|
232
|
+
if (servers.length === 0) {
|
|
233
|
+
this.log("No tools to report");
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
const totalTools = servers.reduce((acc, s) => acc + s.tools.length, 0);
|
|
237
|
+
this.log(`Reporting ${totalTools} tools from ${servers.length} servers`);
|
|
238
|
+
try {
|
|
239
|
+
const token = await this.getToken();
|
|
240
|
+
const response = await safeFetch(`${this.endpoint}/api/mcp-visibility/tools`, {
|
|
241
|
+
method: "POST",
|
|
242
|
+
headers: {
|
|
243
|
+
"Content-Type": "application/json",
|
|
244
|
+
Authorization: `Bearer ${token}`,
|
|
245
|
+
},
|
|
246
|
+
body: JSON.stringify({
|
|
247
|
+
hostname: this.hostname,
|
|
248
|
+
deviceId: this.deviceId,
|
|
249
|
+
servers,
|
|
250
|
+
}),
|
|
251
|
+
});
|
|
252
|
+
if (!response.ok) {
|
|
253
|
+
const text = await response.text();
|
|
254
|
+
throw new Error(`Tools report failed: ${response.status} ${text}`);
|
|
255
|
+
}
|
|
256
|
+
const result = (await response.json());
|
|
257
|
+
this.log(`Tools reported successfully: ${result.toolsUpserted} tools upserted`);
|
|
258
|
+
}
|
|
259
|
+
catch (error) {
|
|
260
|
+
// Non-fatal - log and continue
|
|
261
|
+
this.log("Failed to report tools:", error);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
224
264
|
}
|
|
225
265
|
//# sourceMappingURL=sonoma-client.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sonoma-client.js","sourceRoot":"","sources":["../src/sonoma-client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EACL,UAAU,EACV,cAAc,EACd,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,UAAU,EACV,SAAS,GACV,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"sonoma-client.js","sourceRoot":"","sources":["../src/sonoma-client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EACL,UAAU,EACV,cAAc,EACd,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,UAAU,EACV,SAAS,GACV,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAgBpE,sBAAsB;AACtB,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;AAC9C,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,EAAE,uBAAuB,CAAC,CAAC;AAC7D,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAC9B,MAAM,mBAAmB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO;AAErD,MAAM,OAAO,YAAY;IACf,QAAQ,CAAS;IACjB,QAAQ,CAAS;IACjB,QAAQ,CAAS;IACjB,SAAS,GAAkB,IAAI,CAAC;IAChC,aAAa,GAAoB,EAAE,CAAC;IACpC,aAAa,GAA0C,IAAI,CAAC;IAC5D,KAAK,CAAU;IAEvB,YAAY,OAAkE;QAC5E,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACpD,IAAI,CAAC,QAAQ,GAAG,QAAQ,EAAE,CAAC;QAC3B,IAAI,CAAC,QAAQ,GAAG,iBAAiB,EAAE,CAAC;QACpC,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC;QAC3C,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,KAAK,CAAC;IACtC,CAAC;IAEO,GAAG,CAAC,OAAe,EAAE,GAAG,IAAe;QAC7C,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,2DAA2D;YAC3D,oFAAoF;YACpF,OAAO,CAAC,KAAK,CAAC,mBAAmB,OAAO,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,QAAQ;QACpB,wBAAwB;QACxB,IAAI,CAAC;YACH,OAAO,MAAM,cAAc,CAAC,EAAE,cAAc,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QACpF,CAAC;QAAC,MAAM,CAAC;YACP,wCAAwC;YACxC,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;gBACnB,IAAI,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;gBAC/C,OAAO,IAAI,CAAC,SAAS,CAAC;YACxB,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,gEAAgE,CAAC,CAAC;QACpF,CAAC;IACH,CAAC;IAED;;OAEG;IACH,mBAAmB,CAAC,UAAU,GAAG,KAAK;QACpC,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,OAAO;QACT,CAAC;QAED,IAAI,CAAC,aAAa,GAAG,WAAW,CAAC,GAAG,EAAE;YACpC,IAAI,CAAC,cAAc,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;gBAClC,IAAI,CAAC,GAAG,CAAC,4BAA4B,EAAE,GAAG,CAAC,CAAC;YAC9C,CAAC,CAAC,CAAC;QACL,CAAC,EAAE,UAAU,CAAC,CAAC;QAEf,IAAI,CAAC,GAAG,CAAC,iCAAiC,UAAU,IAAI,CAAC,CAAC;IAC5D,CAAC;IAED;;OAEG;IACH,kBAAkB;QAChB,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,aAAa,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YAClC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAC5B,CAAC;IACH,CAAC;IAED;;OAEG;IACK,eAAe;QACrB,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC5B,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;IAED;;OAEG;IACK,WAAW,CAAC,MAAuB;QACzC,IAAI,CAAC,eAAe,EAAE,CAAC;QAEvB,mCAAmC;QACnC,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC3B,MAAM,KAAK,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC;YACnC,IAAI,KAAK,CAAC,IAAI,IAAI,mBAAmB,EAAE,CAAC;gBACtC,IAAI,CAAC,GAAG,CAAC,gDAAgD,CAAC,CAAC;gBAC3D,yDAAyD;gBACzD,MAAM,KAAK,GAAG,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;gBAC5E,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;gBAC5D,aAAa,CAAC,UAAU,EAAE,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;YAC1E,CAAC;QACH,CAAC;QAED,yBAAyB;QACzB,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;QACrE,cAAc,CAAC,UAAU,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACnD,IAAI,CAAC,GAAG,CAAC,WAAW,MAAM,CAAC,MAAM,iBAAiB,CAAC,CAAC;IACtD,CAAC;IAED;;OAEG;IACK,YAAY;QAClB,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC5B,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;YAClD,MAAM,MAAM,GAAG,OAAO;iBACnB,KAAK,CAAC,IAAI,CAAC;iBACX,MAAM,CAAC,OAAO,CAAC;iBACf,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAkB,CAAC,CAAC;YACpD,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,GAAG,CAAC,4BAA4B,EAAE,KAAK,CAAC,CAAC;YAC9C,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAED;;OAEG;IACK,cAAc;QACpB,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC3B,UAAU,CAAC,UAAU,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,UAAU,CAAC,KAAoB;QAC7B,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/B,IAAI,CAAC,GAAG,CAAC,iBAAiB,KAAK,CAAC,UAAU,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;QAEhE,wCAAwC;QACxC,IAAI,IAAI,CAAC,aAAa,CAAC,MAAM,IAAI,gBAAgB,EAAE,CAAC;YAClD,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,gBAAgB,GAAG,CAAC,CAAC,CAAC,CAAC;YAC/E,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,cAAc;QAClB,uCAAuC;QACvC,MAAM,UAAU,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QACvC,MAAM,YAAY,GAAG,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC;QAC7C,IAAI,CAAC,aAAa,GAAG,EAAE,CAAC;QAExB,MAAM,SAAS,GAAG,CAAC,GAAG,UAAU,EAAE,GAAG,YAAY,CAAC,CAAC;QACnD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3B,OAAO;QACT,CAAC;QAED,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;YAEpC,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,GAAG,IAAI,CAAC,QAAQ,+BAA+B,EAAE;gBAChF,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;oBAClC,aAAa,EAAE,UAAU,KAAK,EAAE;iBACjC;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;oBACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;oBACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ;oBACvB,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;wBAC5B,UAAU,EAAE,CAAC,CAAC,UAAU;wBACxB,QAAQ,EAAE,CAAC,CAAC,QAAQ;wBACpB,SAAS,EAAE,CAAC,CAAC,SAAS;wBACtB,UAAU,EAAE,CAAC,CAAC,UAAU;wBACxB,MAAM,EAAE,CAAC,CAAC,MAAM;wBAChB,YAAY,EAAE,CAAC,CAAC,YAAY;wBAC5B,YAAY,EAAE,CAAC,CAAC,YAAY;qBAC7B,CAAC,CAAC;iBACJ,CAAC;aACH,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;gBACnC,MAAM,IAAI,KAAK,CAAC,qBAAqB,QAAQ,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC,CAAC;YAClE,CAAC;YAED,6BAA6B;YAC7B,IAAI,CAAC,cAAc,EAAE,CAAC;YACtB,IAAI,CAAC,GAAG,CAAC,WAAW,SAAS,CAAC,MAAM,sBAAsB,UAAU,CAAC,MAAM,eAAe,YAAY,CAAC,MAAM,eAAe,CAAC,CAAC;QAChI,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,+DAA+D;YAC/D,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,GAAG,YAAY,CAAC,CAAC;YAC5C,6CAA6C;YAC7C,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC1B,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;YAC/B,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,WAAW;QACf,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;YAEpC,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,GAAG,IAAI,CAAC,QAAQ,4BAA4B,EAAE;gBAC7E,OAAO,EAAE;oBACP,aAAa,EAAE,UAAU,KAAK,EAAE;iBACjC;aACF,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;gBACnC,MAAM,IAAI,KAAK,CAAC,wBAAwB,QAAQ,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC,CAAC;YACrE,CAAC;YAED,MAAM,MAAM,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAmB,CAAC;YACzD,IAAI,CAAC,GAAG,CAAC,wBAAwB,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,CAAC,MAAM,QAAQ,CAAC,CAAC;YAC7E,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,GAAG,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;YAC3C,gDAAgD;YAChD,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,eAAe,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;QACpE,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,WAAW,CACf,OAQE;QAEF,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,IAAI,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;YAC/B,OAAO;QACT,CAAC;QAED,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACvE,IAAI,CAAC,GAAG,CAAC,aAAa,UAAU,eAAe,OAAO,CAAC,MAAM,UAAU,CAAC,CAAC;QAEzE,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;YAEpC,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,GAAG,IAAI,CAAC,QAAQ,2BAA2B,EAAE;gBAC5E,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;oBAClC,aAAa,EAAE,UAAU,KAAK,EAAE;iBACjC;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;oBACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;oBACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ;oBACvB,OAAO;iBACR,CAAC;aACH,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;gBACnC,MAAM,IAAI,KAAK,CAAC,wBAAwB,QAAQ,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC,CAAC;YACrE,CAAC;YAED,MAAM,MAAM,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAgD,CAAC;YACtF,IAAI,CAAC,GAAG,CAAC,gCAAgC,MAAM,CAAC,aAAa,iBAAiB,CAAC,CAAC;QAClF,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,+BAA+B;YAC/B,IAAI,CAAC,GAAG,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lightweight SSRF protection for the MCP Gateway CLI.
|
|
3
|
+
*
|
|
4
|
+
* The gateway is a CLI tool running on the user's local machine, so
|
|
5
|
+
* loopback addresses (localhost / 127.x) are intentionally allowed —
|
|
6
|
+
* dev servers legitimately bind there.
|
|
7
|
+
*
|
|
8
|
+
* What IS blocked:
|
|
9
|
+
* - Cloud metadata endpoints (GCP, AWS, Azure hostname variants)
|
|
10
|
+
* - RFC 1918 private ranges (10.x, 172.16-31.x, 192.168.x)
|
|
11
|
+
* - Link-local / cloud metadata IPs (169.254.0.0/16)
|
|
12
|
+
* - "This network" (0.0.0.0/8)
|
|
13
|
+
* - IPv6 private ranges (fc00::/7 unique-local, fe80::/10 link-local)
|
|
14
|
+
* - IPv4-mapped IPv6 addresses (::ffff:x.x.x.x) that embed blocked IPv4
|
|
15
|
+
*
|
|
16
|
+
* DNS pinning prevents TOCTOU / DNS rebinding attacks by using the
|
|
17
|
+
* validated IP address for the actual TCP connection.
|
|
18
|
+
*
|
|
19
|
+
* Automatic redirects are disabled so every hop can be validated
|
|
20
|
+
* independently, preventing redirect-based SSRF.
|
|
21
|
+
*/
|
|
22
|
+
/** Convert dotted-quad IPv4 to unsigned 32-bit number. */
|
|
23
|
+
export declare function ipToNum(ip: string): number;
|
|
24
|
+
/**
|
|
25
|
+
* Check whether an IP address falls in a blocked range.
|
|
26
|
+
*
|
|
27
|
+
* Handles:
|
|
28
|
+
* - Plain IPv4 (e.g. "10.0.0.1")
|
|
29
|
+
* - IPv4-mapped IPv6 (e.g. "::ffff:10.0.0.1") — extracts and checks the embedded IPv4
|
|
30
|
+
* - IPv6 link-local (fe80::/10) and unique-local (fc00::/7)
|
|
31
|
+
*/
|
|
32
|
+
export declare function isBlockedIP(ip: string): boolean;
|
|
33
|
+
export interface ValidatedUrl {
|
|
34
|
+
url: URL;
|
|
35
|
+
resolvedAddress: string | null;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Validate that a URL is safe to fetch (not targeting private infrastructure).
|
|
39
|
+
*
|
|
40
|
+
* Returns the validated URL and the first resolved IP for DNS pinning.
|
|
41
|
+
*
|
|
42
|
+
* Checks:
|
|
43
|
+
* 1. Protocol is http: or https:
|
|
44
|
+
* 2. Hostname is not a cloud metadata endpoint
|
|
45
|
+
* 3. Resolved IP addresses are not in blocked private ranges
|
|
46
|
+
*
|
|
47
|
+
* Throws on any violation so callers get a clear error.
|
|
48
|
+
*/
|
|
49
|
+
export declare function validateUrl(urlString: string): Promise<ValidatedUrl>;
|
|
50
|
+
/**
|
|
51
|
+
* Drop-in replacement for `fetch()` that validates the target URL first.
|
|
52
|
+
*
|
|
53
|
+
* - Rejects blocked destinations (cloud metadata, private infrastructure)
|
|
54
|
+
* - Pins DNS to prevent rebinding between validation and connection
|
|
55
|
+
* - Disables automatic redirects and re-validates each hop
|
|
56
|
+
* - Limits redirect depth to 10
|
|
57
|
+
*/
|
|
58
|
+
export declare function safeFetch(urlString: string, init?: RequestInit, remainingRedirects?: number): Promise<Response>;
|
|
59
|
+
//# sourceMappingURL=ssrf-protection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ssrf-protection.d.ts","sourceRoot":"","sources":["../src/ssrf-protection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AA0BH,0DAA0D;AAC1D,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAS1C;AAID;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAmB/C;AAoBD,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,GAAG,CAAC;IACT,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CA+C1E;AAuGD;;;;;;;GAOG;AACH,wBAAsB,SAAS,CAC7B,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,WAAW,EAClB,kBAAkB,SAAK,GACtB,OAAO,CAAC,QAAQ,CAAC,CAsBnB"}
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lightweight SSRF protection for the MCP Gateway CLI.
|
|
3
|
+
*
|
|
4
|
+
* The gateway is a CLI tool running on the user's local machine, so
|
|
5
|
+
* loopback addresses (localhost / 127.x) are intentionally allowed —
|
|
6
|
+
* dev servers legitimately bind there.
|
|
7
|
+
*
|
|
8
|
+
* What IS blocked:
|
|
9
|
+
* - Cloud metadata endpoints (GCP, AWS, Azure hostname variants)
|
|
10
|
+
* - RFC 1918 private ranges (10.x, 172.16-31.x, 192.168.x)
|
|
11
|
+
* - Link-local / cloud metadata IPs (169.254.0.0/16)
|
|
12
|
+
* - "This network" (0.0.0.0/8)
|
|
13
|
+
* - IPv6 private ranges (fc00::/7 unique-local, fe80::/10 link-local)
|
|
14
|
+
* - IPv4-mapped IPv6 addresses (::ffff:x.x.x.x) that embed blocked IPv4
|
|
15
|
+
*
|
|
16
|
+
* DNS pinning prevents TOCTOU / DNS rebinding attacks by using the
|
|
17
|
+
* validated IP address for the actual TCP connection.
|
|
18
|
+
*
|
|
19
|
+
* Automatic redirects are disabled so every hop can be validated
|
|
20
|
+
* independently, preventing redirect-based SSRF.
|
|
21
|
+
*/
|
|
22
|
+
import dns from "node:dns/promises";
|
|
23
|
+
import http from "node:http";
|
|
24
|
+
import https from "node:https";
|
|
25
|
+
import net from "node:net";
|
|
26
|
+
// Dangerous private IPv4 ranges to block (excludes loopback which is safe for a CLI).
|
|
27
|
+
const BLOCKED_IP_RANGES = [
|
|
28
|
+
{ start: ipToNum("10.0.0.0"), end: ipToNum("10.255.255.255") }, // Class A private
|
|
29
|
+
{ start: ipToNum("172.16.0.0"), end: ipToNum("172.31.255.255") }, // Class B private
|
|
30
|
+
{ start: ipToNum("192.168.0.0"), end: ipToNum("192.168.255.255") }, // Class C private
|
|
31
|
+
{ start: ipToNum("169.254.0.0"), end: ipToNum("169.254.255.255") }, // Link-local / cloud metadata
|
|
32
|
+
{ start: ipToNum("0.0.0.0"), end: ipToNum("0.255.255.255") }, // "This" network
|
|
33
|
+
];
|
|
34
|
+
// Cloud metadata hostnames across GCP, AWS, and Azure.
|
|
35
|
+
// Loopback (localhost, 127.0.0.1) is intentionally NOT blocked — see module docstring.
|
|
36
|
+
const BLOCKED_HOSTNAMES = new Set([
|
|
37
|
+
"metadata.google.internal", // GCP
|
|
38
|
+
"metadata", // GCP short name
|
|
39
|
+
"metadata.goog", // GCP alternative
|
|
40
|
+
"169.254.169.254", // AWS / GCP / Azure (also caught by IP range check)
|
|
41
|
+
"fd00:ec2::254", // AWS IPv6 metadata
|
|
42
|
+
]);
|
|
43
|
+
/** Convert dotted-quad IPv4 to unsigned 32-bit number. */
|
|
44
|
+
export function ipToNum(ip) {
|
|
45
|
+
const p = ip.split(".");
|
|
46
|
+
return (((Number.parseInt(p[0]) << 24) |
|
|
47
|
+
(Number.parseInt(p[1]) << 16) |
|
|
48
|
+
(Number.parseInt(p[2]) << 8) |
|
|
49
|
+
Number.parseInt(p[3])) >>>
|
|
50
|
+
0);
|
|
51
|
+
}
|
|
52
|
+
const IPV4_MAPPED_PREFIX = "::ffff:";
|
|
53
|
+
/**
|
|
54
|
+
* Check whether an IP address falls in a blocked range.
|
|
55
|
+
*
|
|
56
|
+
* Handles:
|
|
57
|
+
* - Plain IPv4 (e.g. "10.0.0.1")
|
|
58
|
+
* - IPv4-mapped IPv6 (e.g. "::ffff:10.0.0.1") — extracts and checks the embedded IPv4
|
|
59
|
+
* - IPv6 link-local (fe80::/10) and unique-local (fc00::/7)
|
|
60
|
+
*/
|
|
61
|
+
export function isBlockedIP(ip) {
|
|
62
|
+
// IPv4-mapped IPv6 (::ffff:x.x.x.x) — extract and re-check as IPv4
|
|
63
|
+
if (ip.toLowerCase().startsWith(IPV4_MAPPED_PREFIX)) {
|
|
64
|
+
const embedded = ip.slice(IPV4_MAPPED_PREFIX.length);
|
|
65
|
+
if (net.isIPv4(embedded)) {
|
|
66
|
+
return isBlockedIPv4(embedded);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (net.isIPv4(ip)) {
|
|
70
|
+
return isBlockedIPv4(ip);
|
|
71
|
+
}
|
|
72
|
+
// IPv6 private ranges
|
|
73
|
+
if (net.isIPv6(ip)) {
|
|
74
|
+
return isBlockedIPv6(ip);
|
|
75
|
+
}
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
function isBlockedIPv4(ip) {
|
|
79
|
+
const n = ipToNum(ip);
|
|
80
|
+
return BLOCKED_IP_RANGES.some((r) => n >= r.start && n <= r.end);
|
|
81
|
+
}
|
|
82
|
+
function isBlockedIPv6(ip) {
|
|
83
|
+
const lower = ip.toLowerCase();
|
|
84
|
+
// Expand to check first group
|
|
85
|
+
const firstGroup = Number.parseInt(lower.split(":")[0] || "0", 16);
|
|
86
|
+
// fe80::/10 — link-local
|
|
87
|
+
if ((firstGroup & 0xffc0) === 0xfe80)
|
|
88
|
+
return true;
|
|
89
|
+
// fc00::/7 — unique-local (ULA)
|
|
90
|
+
if ((firstGroup & 0xfe00) === 0xfc00)
|
|
91
|
+
return true;
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Validate that a URL is safe to fetch (not targeting private infrastructure).
|
|
96
|
+
*
|
|
97
|
+
* Returns the validated URL and the first resolved IP for DNS pinning.
|
|
98
|
+
*
|
|
99
|
+
* Checks:
|
|
100
|
+
* 1. Protocol is http: or https:
|
|
101
|
+
* 2. Hostname is not a cloud metadata endpoint
|
|
102
|
+
* 3. Resolved IP addresses are not in blocked private ranges
|
|
103
|
+
*
|
|
104
|
+
* Throws on any violation so callers get a clear error.
|
|
105
|
+
*/
|
|
106
|
+
export async function validateUrl(urlString) {
|
|
107
|
+
let url;
|
|
108
|
+
try {
|
|
109
|
+
url = new URL(urlString);
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
throw new Error("Invalid URL format");
|
|
113
|
+
}
|
|
114
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
115
|
+
throw new Error(`Protocol ${url.protocol} is not allowed. Only HTTP and HTTPS are permitted.`);
|
|
116
|
+
}
|
|
117
|
+
const hostname = url.hostname.toLowerCase();
|
|
118
|
+
if (BLOCKED_HOSTNAMES.has(hostname)) {
|
|
119
|
+
throw new Error(`Access to ${hostname} is blocked for security reasons`);
|
|
120
|
+
}
|
|
121
|
+
// If hostname is already a literal IP, check it directly
|
|
122
|
+
if (net.isIP(hostname)) {
|
|
123
|
+
if (isBlockedIP(hostname)) {
|
|
124
|
+
throw new Error(`Access to private IP ${hostname} is blocked for security reasons`);
|
|
125
|
+
}
|
|
126
|
+
return { url, resolvedAddress: null };
|
|
127
|
+
}
|
|
128
|
+
// Resolve via the system resolver (respects /etc/hosts, unlike dns.resolve4).
|
|
129
|
+
try {
|
|
130
|
+
const results = await dns.lookup(hostname, { all: true });
|
|
131
|
+
for (const { address } of results) {
|
|
132
|
+
if (isBlockedIP(address)) {
|
|
133
|
+
throw new Error(`Hostname ${hostname} resolves to private IP ${address}, access blocked for security reasons`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return { url, resolvedAddress: results[0]?.address ?? null };
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
if (error instanceof Error && "code" in error && error.code === "ENOTFOUND") {
|
|
140
|
+
throw new Error(`Unable to resolve hostname: ${hostname}`);
|
|
141
|
+
}
|
|
142
|
+
throw error;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Fetch using the pre-resolved IP address to prevent DNS rebinding (TOCTOU).
|
|
147
|
+
*
|
|
148
|
+
* Uses node:http/https with a custom `lookup` function so the original
|
|
149
|
+
* hostname is preserved for TLS SNI and Host header while connecting to
|
|
150
|
+
* the validated IP.
|
|
151
|
+
*/
|
|
152
|
+
function fetchWithDnsPinning(url, resolvedAddress, init) {
|
|
153
|
+
// If hostname is already an IP (no DNS resolution was done), use fetch directly
|
|
154
|
+
if (!resolvedAddress) {
|
|
155
|
+
return fetch(url.toString(), init);
|
|
156
|
+
}
|
|
157
|
+
return new Promise((resolve, reject) => {
|
|
158
|
+
const isHttps = url.protocol === "https:";
|
|
159
|
+
const mod = isHttps ? https : http;
|
|
160
|
+
const headers = {};
|
|
161
|
+
if (init?.headers) {
|
|
162
|
+
const h = new Headers(init.headers);
|
|
163
|
+
h.forEach((value, key) => {
|
|
164
|
+
headers[key] = value;
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
const family = net.isIPv6(resolvedAddress) ? 6 : 4;
|
|
168
|
+
const options = {
|
|
169
|
+
hostname: url.hostname,
|
|
170
|
+
port: url.port || (isHttps ? 443 : 80),
|
|
171
|
+
path: url.pathname + url.search,
|
|
172
|
+
method: init?.method || "GET",
|
|
173
|
+
headers,
|
|
174
|
+
// Pin DNS: return the already-validated IP instead of resolving again.
|
|
175
|
+
// Hostname is still used for TLS SNI so certificate validation works.
|
|
176
|
+
// Bun's http client expects cb(null, [{address, family}]) while Node
|
|
177
|
+
// expects cb(null, address, family). Pass both forms to be safe.
|
|
178
|
+
lookup: (...args) => {
|
|
179
|
+
const cb = typeof args[1] === "function" ? args[1] : args[2];
|
|
180
|
+
cb(null, [{ address: resolvedAddress, family }]);
|
|
181
|
+
},
|
|
182
|
+
};
|
|
183
|
+
const req = mod.request(options, (res) => {
|
|
184
|
+
const chunks = [];
|
|
185
|
+
res.on("data", (chunk) => chunks.push(chunk));
|
|
186
|
+
res.on("end", () => {
|
|
187
|
+
const body = Buffer.concat(chunks);
|
|
188
|
+
const responseHeaders = new Headers();
|
|
189
|
+
for (const [key, value] of Object.entries(res.headers)) {
|
|
190
|
+
if (value !== undefined) {
|
|
191
|
+
if (Array.isArray(value)) {
|
|
192
|
+
for (const v of value)
|
|
193
|
+
responseHeaders.append(key, v);
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
responseHeaders.set(key, value);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
resolve(new Response(body, {
|
|
201
|
+
status: res.statusCode ?? 200,
|
|
202
|
+
statusText: res.statusMessage ?? "",
|
|
203
|
+
headers: responseHeaders,
|
|
204
|
+
}));
|
|
205
|
+
});
|
|
206
|
+
res.on("error", reject);
|
|
207
|
+
});
|
|
208
|
+
if (init?.signal) {
|
|
209
|
+
if (init.signal.aborted) {
|
|
210
|
+
req.destroy();
|
|
211
|
+
reject(new DOMException("The operation was aborted.", "AbortError"));
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
init.signal.addEventListener("abort", () => {
|
|
215
|
+
req.destroy();
|
|
216
|
+
reject(new DOMException("The operation was aborted.", "AbortError"));
|
|
217
|
+
}, { once: true });
|
|
218
|
+
}
|
|
219
|
+
req.on("error", reject);
|
|
220
|
+
if (init?.body) {
|
|
221
|
+
req.write(init.body);
|
|
222
|
+
}
|
|
223
|
+
req.end();
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Drop-in replacement for `fetch()` that validates the target URL first.
|
|
228
|
+
*
|
|
229
|
+
* - Rejects blocked destinations (cloud metadata, private infrastructure)
|
|
230
|
+
* - Pins DNS to prevent rebinding between validation and connection
|
|
231
|
+
* - Disables automatic redirects and re-validates each hop
|
|
232
|
+
* - Limits redirect depth to 10
|
|
233
|
+
*/
|
|
234
|
+
export async function safeFetch(urlString, init, remainingRedirects = 10) {
|
|
235
|
+
if (remainingRedirects <= 0) {
|
|
236
|
+
throw new Error("Too many redirects");
|
|
237
|
+
}
|
|
238
|
+
const { url: validatedUrl, resolvedAddress } = await validateUrl(urlString);
|
|
239
|
+
const response = await fetchWithDnsPinning(validatedUrl, resolvedAddress, {
|
|
240
|
+
...init,
|
|
241
|
+
redirect: "manual",
|
|
242
|
+
});
|
|
243
|
+
// Re-validate redirect targets before following them
|
|
244
|
+
if (response.status >= 300 && response.status < 400) {
|
|
245
|
+
const location = response.headers.get("location");
|
|
246
|
+
if (location) {
|
|
247
|
+
const absoluteRedirect = new URL(location, urlString).toString();
|
|
248
|
+
return safeFetch(absoluteRedirect, init, remainingRedirects - 1);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return response;
|
|
252
|
+
}
|
|
253
|
+
//# sourceMappingURL=ssrf-protection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ssrf-protection.js","sourceRoot":"","sources":["../src/ssrf-protection.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
export interface McpServerConfig {
|
|
5
5
|
/** Server name (unique identifier) */
|
|
6
6
|
name: string;
|
|
7
|
-
/** Command to spawn the server */
|
|
8
|
-
command
|
|
7
|
+
/** Command to spawn the server (stdio transport) */
|
|
8
|
+
command?: string;
|
|
9
9
|
/** Arguments to pass to the command */
|
|
10
10
|
args?: string[];
|
|
11
11
|
/** Environment variables */
|
|
@@ -14,6 +14,10 @@ export interface McpServerConfig {
|
|
|
14
14
|
cwd?: string;
|
|
15
15
|
/** Package name for policy matching (e.g., @anthropic/mcp-server-time) */
|
|
16
16
|
packageName?: string;
|
|
17
|
+
/** URL for HTTP/SSE transport (alternative to command) */
|
|
18
|
+
url?: string;
|
|
19
|
+
/** HTTP headers for URL-based servers */
|
|
20
|
+
headers?: Record<string, string>;
|
|
17
21
|
}
|
|
18
22
|
export interface GatewayConfig {
|
|
19
23
|
/** Upstream MCP servers to proxy */
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,eAAe;IAC9B,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,eAAe;IAC9B,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uCAAuC;IACvC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,4BAA4B;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,wBAAwB;IACxB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0DAA0D;IAC1D,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,yCAAyC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,aAAa;IAC5B,oCAAoC;IACpC,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,2DAA2D;IAC3D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gFAAgF;IAChF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,2BAA2B;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;IACxC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,eAAe,CAAC;IACxB,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;CACpB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sonoma-security/mcp-gateway",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Local MCP gateway for tool-level visibility and enforcement",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"typecheck": "tsc --noEmit"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@modelcontextprotocol/sdk": "
|
|
37
|
+
"@modelcontextprotocol/sdk": "1.26.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@types/node": "^22.15.29"
|