@paretools/http 0.14.1 → 0.15.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/dist/__tests__/url-validation.test.d.ts +2 -0
- package/dist/__tests__/url-validation.test.d.ts.map +1 -0
- package/dist/__tests__/url-validation.test.js +231 -0
- package/dist/__tests__/url-validation.test.js.map +1 -0
- package/dist/lib/url-validation.d.ts +31 -3
- package/dist/lib/url-validation.d.ts.map +1 -1
- package/dist/lib/url-validation.js +257 -3
- package/dist/lib/url-validation.js.map +1 -1
- package/dist/tools/get.d.ts.map +1 -1
- package/dist/tools/get.js +9 -5
- package/dist/tools/get.js.map +1 -1
- package/dist/tools/head.d.ts.map +1 -1
- package/dist/tools/head.js +9 -5
- package/dist/tools/head.js.map +1 -1
- package/dist/tools/post.d.ts.map +1 -1
- package/dist/tools/post.js +9 -5
- package/dist/tools/post.js.map +1 -1
- package/dist/tools/request.d.ts.map +1 -1
- package/dist/tools/request.js +16 -8
- package/dist/tools/request.js.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"url-validation.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/url-validation.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import { assertSafeUrl, assertSafeResolve, assertSafeCookie, assertSafeFormValues, isPrivateIP, assertSafeHeader, } from "../lib/url-validation.js";
|
|
3
|
+
/* ------------------------------------------------------------------ */
|
|
4
|
+
/* assertSafeUrl — scheme checks */
|
|
5
|
+
/* ------------------------------------------------------------------ */
|
|
6
|
+
describe("assertSafeUrl — scheme validation", () => {
|
|
7
|
+
it("allows http:// URLs", async () => {
|
|
8
|
+
await expect(assertSafeUrl("http://example.com")).resolves.toBeUndefined();
|
|
9
|
+
});
|
|
10
|
+
it("allows https:// URLs", async () => {
|
|
11
|
+
await expect(assertSafeUrl("https://example.com")).resolves.toBeUndefined();
|
|
12
|
+
});
|
|
13
|
+
it("rejects empty URL", async () => {
|
|
14
|
+
await expect(assertSafeUrl("")).rejects.toThrow("URL must not be empty");
|
|
15
|
+
});
|
|
16
|
+
it("rejects file:// scheme", async () => {
|
|
17
|
+
await expect(assertSafeUrl("file:///etc/passwd")).rejects.toThrow("Unsafe URL scheme");
|
|
18
|
+
});
|
|
19
|
+
it("rejects ftp:// scheme", async () => {
|
|
20
|
+
await expect(assertSafeUrl("ftp://example.com")).rejects.toThrow("Unsafe URL scheme");
|
|
21
|
+
});
|
|
22
|
+
it("rejects gopher:// scheme", async () => {
|
|
23
|
+
await expect(assertSafeUrl("gopher://evil.com")).rejects.toThrow("Unsafe URL scheme");
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
/* ------------------------------------------------------------------ */
|
|
27
|
+
/* assertSafeUrl — SSRF private IP blocking */
|
|
28
|
+
/* ------------------------------------------------------------------ */
|
|
29
|
+
describe("assertSafeUrl — SSRF protection", () => {
|
|
30
|
+
// Save and restore env
|
|
31
|
+
let origAllow;
|
|
32
|
+
beforeEach(() => {
|
|
33
|
+
origAllow = process.env.PARE_HTTP_ALLOW_PRIVATE;
|
|
34
|
+
delete process.env.PARE_HTTP_ALLOW_PRIVATE;
|
|
35
|
+
});
|
|
36
|
+
afterEach(() => {
|
|
37
|
+
if (origAllow !== undefined)
|
|
38
|
+
process.env.PARE_HTTP_ALLOW_PRIVATE = origAllow;
|
|
39
|
+
else
|
|
40
|
+
delete process.env.PARE_HTTP_ALLOW_PRIVATE;
|
|
41
|
+
});
|
|
42
|
+
it("blocks 127.0.0.1 (loopback)", async () => {
|
|
43
|
+
await expect(assertSafeUrl("http://127.0.0.1/")).rejects.toThrow("private/reserved IP");
|
|
44
|
+
});
|
|
45
|
+
it("blocks 127.0.0.2 (loopback range)", async () => {
|
|
46
|
+
await expect(assertSafeUrl("http://127.0.0.2/")).rejects.toThrow("private/reserved IP");
|
|
47
|
+
});
|
|
48
|
+
it("blocks 10.0.0.1 (RFC 1918)", async () => {
|
|
49
|
+
await expect(assertSafeUrl("http://10.0.0.1/")).rejects.toThrow("private/reserved IP");
|
|
50
|
+
});
|
|
51
|
+
it("blocks 172.16.0.1 (RFC 1918)", async () => {
|
|
52
|
+
await expect(assertSafeUrl("http://172.16.0.1/")).rejects.toThrow("private/reserved IP");
|
|
53
|
+
});
|
|
54
|
+
it("blocks 192.168.1.1 (RFC 1918)", async () => {
|
|
55
|
+
await expect(assertSafeUrl("http://192.168.1.1/")).rejects.toThrow("private/reserved IP");
|
|
56
|
+
});
|
|
57
|
+
it("blocks 169.254.169.254 (link-local / cloud metadata)", async () => {
|
|
58
|
+
await expect(assertSafeUrl("http://169.254.169.254/")).rejects.toThrow("private/reserved IP");
|
|
59
|
+
});
|
|
60
|
+
it("blocks 0.0.0.0", async () => {
|
|
61
|
+
await expect(assertSafeUrl("http://0.0.0.0/")).rejects.toThrow("private/reserved IP");
|
|
62
|
+
});
|
|
63
|
+
it("blocks [::1] (IPv6 loopback)", async () => {
|
|
64
|
+
await expect(assertSafeUrl("http://[::1]/")).rejects.toThrow("private/reserved IP");
|
|
65
|
+
});
|
|
66
|
+
it("blocks metadata.google.internal", async () => {
|
|
67
|
+
await expect(assertSafeUrl("http://metadata.google.internal/")).rejects.toThrow("metadata hostname");
|
|
68
|
+
});
|
|
69
|
+
it("blocks metadata.internal", async () => {
|
|
70
|
+
await expect(assertSafeUrl("http://metadata.internal/")).rejects.toThrow("metadata hostname");
|
|
71
|
+
});
|
|
72
|
+
// IP obfuscation
|
|
73
|
+
it("blocks decimal IP 2130706433 (127.0.0.1)", async () => {
|
|
74
|
+
await expect(assertSafeUrl("http://2130706433/")).rejects.toThrow("private/reserved IP");
|
|
75
|
+
});
|
|
76
|
+
it("blocks hex IP 0x7f000001 (127.0.0.1)", async () => {
|
|
77
|
+
await expect(assertSafeUrl("http://0x7f000001/")).rejects.toThrow("private/reserved IP");
|
|
78
|
+
});
|
|
79
|
+
it("blocks octal IP 0177.0.0.1 (127.0.0.1)", async () => {
|
|
80
|
+
await expect(assertSafeUrl("http://0177.0.0.1/")).rejects.toThrow("private/reserved IP");
|
|
81
|
+
});
|
|
82
|
+
// Opt-out
|
|
83
|
+
it("allows private IPs when PARE_HTTP_ALLOW_PRIVATE=true", async () => {
|
|
84
|
+
process.env.PARE_HTTP_ALLOW_PRIVATE = "true";
|
|
85
|
+
await expect(assertSafeUrl("http://127.0.0.1/")).resolves.toBeUndefined();
|
|
86
|
+
});
|
|
87
|
+
it("does NOT allow private IPs when PARE_HTTP_ALLOW_PRIVATE is set to other values", async () => {
|
|
88
|
+
process.env.PARE_HTTP_ALLOW_PRIVATE = "yes";
|
|
89
|
+
await expect(assertSafeUrl("http://127.0.0.1/")).rejects.toThrow("private/reserved IP");
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
/* ------------------------------------------------------------------ */
|
|
93
|
+
/* isPrivateIP */
|
|
94
|
+
/* ------------------------------------------------------------------ */
|
|
95
|
+
describe("isPrivateIP", () => {
|
|
96
|
+
it.each([
|
|
97
|
+
"127.0.0.1",
|
|
98
|
+
"10.0.0.1",
|
|
99
|
+
"172.16.0.1",
|
|
100
|
+
"192.168.0.1",
|
|
101
|
+
"169.254.169.254",
|
|
102
|
+
"0.0.0.0",
|
|
103
|
+
"::1",
|
|
104
|
+
])("returns true for private IP %s", (ip) => {
|
|
105
|
+
expect(isPrivateIP(ip)).toBe(true);
|
|
106
|
+
});
|
|
107
|
+
it.each(["8.8.8.8", "1.1.1.1", "93.184.216.34"])("returns false for public IP %s", (ip) => {
|
|
108
|
+
expect(isPrivateIP(ip)).toBe(false);
|
|
109
|
+
});
|
|
110
|
+
// Obfuscated forms
|
|
111
|
+
it("detects decimal 2130706433 as private (127.0.0.1)", () => {
|
|
112
|
+
expect(isPrivateIP("2130706433")).toBe(true);
|
|
113
|
+
});
|
|
114
|
+
it("detects hex 0x7f000001 as private (127.0.0.1)", () => {
|
|
115
|
+
expect(isPrivateIP("0x7f000001")).toBe(true);
|
|
116
|
+
});
|
|
117
|
+
it("detects octal 0177.0.0.1 as private (127.0.0.1)", () => {
|
|
118
|
+
expect(isPrivateIP("0177.0.0.1")).toBe(true);
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
/* ------------------------------------------------------------------ */
|
|
122
|
+
/* assertSafeResolve — DNS rebinding protection */
|
|
123
|
+
/* ------------------------------------------------------------------ */
|
|
124
|
+
describe("assertSafeResolve", () => {
|
|
125
|
+
let origAllow;
|
|
126
|
+
beforeEach(() => {
|
|
127
|
+
origAllow = process.env.PARE_HTTP_ALLOW_PRIVATE;
|
|
128
|
+
delete process.env.PARE_HTTP_ALLOW_PRIVATE;
|
|
129
|
+
});
|
|
130
|
+
afterEach(() => {
|
|
131
|
+
if (origAllow !== undefined)
|
|
132
|
+
process.env.PARE_HTTP_ALLOW_PRIVATE = origAllow;
|
|
133
|
+
else
|
|
134
|
+
delete process.env.PARE_HTTP_ALLOW_PRIVATE;
|
|
135
|
+
});
|
|
136
|
+
it("allows public IP in resolve", () => {
|
|
137
|
+
expect(() => assertSafeResolve("example.com:443:93.184.216.34")).not.toThrow();
|
|
138
|
+
});
|
|
139
|
+
it("blocks 127.0.0.1 in resolve", () => {
|
|
140
|
+
expect(() => assertSafeResolve("example.com:443:127.0.0.1")).toThrow("private/reserved IP");
|
|
141
|
+
});
|
|
142
|
+
it("blocks 10.0.0.1 in resolve", () => {
|
|
143
|
+
expect(() => assertSafeResolve("example.com:443:10.0.0.1")).toThrow("private/reserved IP");
|
|
144
|
+
});
|
|
145
|
+
it("blocks 192.168.1.1 in resolve", () => {
|
|
146
|
+
expect(() => assertSafeResolve("example.com:443:192.168.1.1")).toThrow("private/reserved IP");
|
|
147
|
+
});
|
|
148
|
+
it("blocks 169.254.169.254 in resolve (metadata endpoint)", () => {
|
|
149
|
+
expect(() => assertSafeResolve("example.com:80:169.254.169.254")).toThrow("private/reserved IP");
|
|
150
|
+
});
|
|
151
|
+
it("blocks multiple addresses if any is private", () => {
|
|
152
|
+
expect(() => assertSafeResolve("example.com:443:93.184.216.34,127.0.0.1")).toThrow("private/reserved IP");
|
|
153
|
+
});
|
|
154
|
+
it("allows when PARE_HTTP_ALLOW_PRIVATE=true", () => {
|
|
155
|
+
process.env.PARE_HTTP_ALLOW_PRIVATE = "true";
|
|
156
|
+
expect(() => assertSafeResolve("example.com:443:127.0.0.1")).not.toThrow();
|
|
157
|
+
});
|
|
158
|
+
it("passes through malformed resolve (lets curl handle it)", () => {
|
|
159
|
+
expect(() => assertSafeResolve("nocolon")).not.toThrow();
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
/* ------------------------------------------------------------------ */
|
|
163
|
+
/* assertSafeCookie — file path rejection */
|
|
164
|
+
/* ------------------------------------------------------------------ */
|
|
165
|
+
describe("assertSafeCookie", () => {
|
|
166
|
+
it("allows standard cookie string", () => {
|
|
167
|
+
expect(() => assertSafeCookie("session=abc123")).not.toThrow();
|
|
168
|
+
});
|
|
169
|
+
it("allows multiple cookies", () => {
|
|
170
|
+
expect(() => assertSafeCookie("a=1; b=2")).not.toThrow();
|
|
171
|
+
});
|
|
172
|
+
it("rejects file path (no = sign)", () => {
|
|
173
|
+
expect(() => assertSafeCookie("/etc/passwd")).toThrow('must be in "name=value" format');
|
|
174
|
+
});
|
|
175
|
+
it("rejects bare cookie jar filename", () => {
|
|
176
|
+
expect(() => assertSafeCookie("cookies.txt")).toThrow('must be in "name=value" format');
|
|
177
|
+
});
|
|
178
|
+
it("rejects Windows file path", () => {
|
|
179
|
+
expect(() => assertSafeCookie("C:\\Users\\cookies.txt")).toThrow('must be in "name=value" format');
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
/* ------------------------------------------------------------------ */
|
|
183
|
+
/* assertSafeFormValues — file exfiltration protection */
|
|
184
|
+
/* ------------------------------------------------------------------ */
|
|
185
|
+
describe("assertSafeFormValues", () => {
|
|
186
|
+
let origAllow;
|
|
187
|
+
beforeEach(() => {
|
|
188
|
+
origAllow = process.env.PARE_HTTP_ALLOW_FILE_UPLOAD;
|
|
189
|
+
delete process.env.PARE_HTTP_ALLOW_FILE_UPLOAD;
|
|
190
|
+
});
|
|
191
|
+
afterEach(() => {
|
|
192
|
+
if (origAllow !== undefined)
|
|
193
|
+
process.env.PARE_HTTP_ALLOW_FILE_UPLOAD = origAllow;
|
|
194
|
+
else
|
|
195
|
+
delete process.env.PARE_HTTP_ALLOW_FILE_UPLOAD;
|
|
196
|
+
});
|
|
197
|
+
it("allows normal form values", () => {
|
|
198
|
+
expect(() => assertSafeFormValues({ name: "John", age: "30" })).not.toThrow();
|
|
199
|
+
});
|
|
200
|
+
it("blocks @filepath in form value", () => {
|
|
201
|
+
expect(() => assertSafeFormValues({ file: "@/etc/passwd" })).toThrow("file upload");
|
|
202
|
+
});
|
|
203
|
+
it("blocks @filepath for Windows paths", () => {
|
|
204
|
+
expect(() => assertSafeFormValues({ file: "@C:\\secrets.txt" })).toThrow("file upload");
|
|
205
|
+
});
|
|
206
|
+
it("allows @filepath when PARE_HTTP_ALLOW_FILE_UPLOAD=true", () => {
|
|
207
|
+
process.env.PARE_HTTP_ALLOW_FILE_UPLOAD = "true";
|
|
208
|
+
expect(() => assertSafeFormValues({ file: "@/etc/passwd" })).not.toThrow();
|
|
209
|
+
});
|
|
210
|
+
it("reports the field name in the error", () => {
|
|
211
|
+
expect(() => assertSafeFormValues({ avatar: "@photo.png" })).toThrow('"avatar"');
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
/* ------------------------------------------------------------------ */
|
|
215
|
+
/* assertSafeHeader — unchanged behavior */
|
|
216
|
+
/* ------------------------------------------------------------------ */
|
|
217
|
+
describe("assertSafeHeader", () => {
|
|
218
|
+
it("allows normal headers", () => {
|
|
219
|
+
expect(() => assertSafeHeader("Content-Type", "application/json")).not.toThrow();
|
|
220
|
+
});
|
|
221
|
+
it("rejects newline in key", () => {
|
|
222
|
+
expect(() => assertSafeHeader("Bad\nKey", "value")).toThrow("must not contain newlines");
|
|
223
|
+
});
|
|
224
|
+
it("rejects newline in value", () => {
|
|
225
|
+
expect(() => assertSafeHeader("Key", "bad\r\nvalue")).toThrow("must not contain newlines");
|
|
226
|
+
});
|
|
227
|
+
it("rejects null byte in value", () => {
|
|
228
|
+
expect(() => assertSafeHeader("Key", "bad\x00value")).toThrow("must not contain newlines");
|
|
229
|
+
});
|
|
230
|
+
});
|
|
231
|
+
//# sourceMappingURL=url-validation.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"url-validation.test.js","sourceRoot":"","sources":["../../src/__tests__/url-validation.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,36 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* Check if an IP address string (v4 or v6) is private/reserved.
|
|
3
|
+
* Exported for use by resolve parameter validation.
|
|
4
4
|
*/
|
|
5
|
-
export declare function
|
|
5
|
+
export declare function isPrivateIP(ip: string): boolean;
|
|
6
|
+
/**
|
|
7
|
+
* Validates that a URL uses only http:// or https:// schemes and does not
|
|
8
|
+
* target private/reserved IP ranges (SSRF protection).
|
|
9
|
+
*
|
|
10
|
+
* Set environment variable PARE_HTTP_ALLOW_PRIVATE=true to disable
|
|
11
|
+
* private IP blocking (e.g., for local development).
|
|
12
|
+
*/
|
|
13
|
+
export declare function assertSafeUrl(url: string): Promise<void>;
|
|
14
|
+
/**
|
|
15
|
+
* Validates that the `resolve` parameter's target IP address is not private/reserved.
|
|
16
|
+
* Format: "host:port:addr" or "host:port:addr,addr2"
|
|
17
|
+
*
|
|
18
|
+
* Blocks DNS rebinding attacks where --resolve is used to redirect
|
|
19
|
+
* requests to private IPs despite the URL appearing safe.
|
|
20
|
+
*/
|
|
21
|
+
export declare function assertSafeResolve(resolve: string): void;
|
|
22
|
+
/**
|
|
23
|
+
* Validates that a cookie value is a cookie string (contains '='), not a file path.
|
|
24
|
+
* curl's -b flag reads cookies from a file if the value doesn't contain '='.
|
|
25
|
+
* This prevents arbitrary file read via the cookie parameter.
|
|
26
|
+
*/
|
|
27
|
+
export declare function assertSafeCookie(cookie: string): void;
|
|
28
|
+
/**
|
|
29
|
+
* Validates that form values do not use @filepath syntax for file uploads
|
|
30
|
+
* unless explicitly allowed via PARE_HTTP_ALLOW_FILE_UPLOAD=true.
|
|
31
|
+
* curl's -F flag reads file contents when the value starts with '@'.
|
|
32
|
+
*/
|
|
33
|
+
export declare function assertSafeFormValues(form: Record<string, string>): void;
|
|
6
34
|
/**
|
|
7
35
|
* Validates that a header key or value does not contain newlines or control characters
|
|
8
36
|
* that could be used for header injection attacks.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"url-validation.d.ts","sourceRoot":"","sources":["../../src/lib/url-validation.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"url-validation.d.ts","sourceRoot":"","sources":["../../src/lib/url-validation.ts"],"names":[],"mappings":"AAsIA;;;GAGG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAgB/C;AAED;;;;;;GAMG;AACH,wBAAsB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAqE9D;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAwBvD;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAOrD;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAWvE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAcjE"}
|
|
@@ -1,8 +1,162 @@
|
|
|
1
|
+
import { lookup } from "node:dns/promises";
|
|
1
2
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
3
|
+
* Private/reserved IPv4 CIDR ranges that should be blocked for SSRF protection.
|
|
4
|
+
* Each entry is [networkAddress, prefixLength].
|
|
4
5
|
*/
|
|
5
|
-
|
|
6
|
+
const PRIVATE_IPV4_RANGES = [
|
|
7
|
+
[ipv4ToNum("0.0.0.0"), 8], // "this" network
|
|
8
|
+
[ipv4ToNum("10.0.0.0"), 8], // RFC 1918
|
|
9
|
+
[ipv4ToNum("100.64.0.0"), 10], // Carrier-grade NAT (RFC 6598)
|
|
10
|
+
[ipv4ToNum("127.0.0.0"), 8], // loopback
|
|
11
|
+
[ipv4ToNum("169.254.0.0"), 16], // link-local
|
|
12
|
+
[ipv4ToNum("172.16.0.0"), 12], // RFC 1918
|
|
13
|
+
[ipv4ToNum("192.0.0.0"), 24], // IETF protocol assignments
|
|
14
|
+
[ipv4ToNum("192.0.2.0"), 24], // TEST-NET-1
|
|
15
|
+
[ipv4ToNum("192.88.99.0"), 24], // 6to4 relay anycast
|
|
16
|
+
[ipv4ToNum("192.168.0.0"), 16], // RFC 1918
|
|
17
|
+
[ipv4ToNum("198.18.0.0"), 15], // benchmark testing
|
|
18
|
+
[ipv4ToNum("198.51.100.0"), 24], // TEST-NET-2
|
|
19
|
+
[ipv4ToNum("203.0.113.0"), 24], // TEST-NET-3
|
|
20
|
+
[ipv4ToNum("224.0.0.0"), 4], // multicast + reserved
|
|
21
|
+
];
|
|
22
|
+
/**
|
|
23
|
+
* Blocked metadata hostnames commonly used by cloud providers.
|
|
24
|
+
*/
|
|
25
|
+
const BLOCKED_HOSTNAMES = new Set(["metadata.google.internal", "metadata.internal", "metadata"]);
|
|
26
|
+
/** Convert dotted-quad IPv4 to 32-bit unsigned number. */
|
|
27
|
+
function ipv4ToNum(ip) {
|
|
28
|
+
const parts = ip.split(".").map(Number);
|
|
29
|
+
return ((parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8) | parts[3]) >>> 0;
|
|
30
|
+
}
|
|
31
|
+
/** Check if an IPv4 address (as number) falls within any private/reserved range. */
|
|
32
|
+
function isPrivateIPv4(ipNum) {
|
|
33
|
+
for (const [network, prefix] of PRIVATE_IPV4_RANGES) {
|
|
34
|
+
const mask = prefix === 0 ? 0 : (~0 << (32 - prefix)) >>> 0;
|
|
35
|
+
if ((ipNum & mask) === (network & mask))
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
/** Private/reserved IPv6 prefixes (normalized lowercase hex). */
|
|
41
|
+
const PRIVATE_IPV6_CHECKS = [
|
|
42
|
+
// ::1 loopback
|
|
43
|
+
(addr) => addr === "::1" || addr === "0000:0000:0000:0000:0000:0000:0000:0001",
|
|
44
|
+
// fe80::/10 link-local
|
|
45
|
+
(addr) => {
|
|
46
|
+
const first = parseInt(addr.split(":")[0] || "0", 16);
|
|
47
|
+
return (first & 0xffc0) === 0xfe80;
|
|
48
|
+
},
|
|
49
|
+
// fc00::/7 unique local
|
|
50
|
+
(addr) => {
|
|
51
|
+
const first = parseInt(addr.split(":")[0] || "0", 16);
|
|
52
|
+
return (first & 0xfe00) === 0xfc00;
|
|
53
|
+
},
|
|
54
|
+
// :: unspecified
|
|
55
|
+
(addr) => addr === "::" || addr === "0000:0000:0000:0000:0000:0000:0000:0000",
|
|
56
|
+
// ::ffff:0:0/96 IPv4-mapped — check the embedded IPv4
|
|
57
|
+
(addr) => {
|
|
58
|
+
const match = addr.match(/^::ffff:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/i);
|
|
59
|
+
if (match) {
|
|
60
|
+
return isPrivateIPv4(ipv4ToNum(match[1]));
|
|
61
|
+
}
|
|
62
|
+
return false;
|
|
63
|
+
},
|
|
64
|
+
];
|
|
65
|
+
/** Check if an IPv6 address string is private/reserved. */
|
|
66
|
+
function isPrivateIPv6(addr) {
|
|
67
|
+
const lower = addr.toLowerCase();
|
|
68
|
+
return PRIVATE_IPV6_CHECKS.some((check) => check(lower));
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Attempt to parse a string as an IPv4 address, handling obfuscation:
|
|
72
|
+
* - Decimal notation: `2130706433` -> `127.0.0.1`
|
|
73
|
+
* - Hex notation: `0x7f000001` -> `127.0.0.1`
|
|
74
|
+
* - Octal notation: `0177.0.0.1` -> `127.0.0.1`
|
|
75
|
+
* - Mixed octal/hex per-octet: `0x7f.0.1`
|
|
76
|
+
*
|
|
77
|
+
* Returns the 32-bit numeric value, or null if not a valid IPv4 address.
|
|
78
|
+
*/
|
|
79
|
+
function parseObfuscatedIPv4(host) {
|
|
80
|
+
// Single-number decimal or hex (e.g., 2130706433 or 0x7f000001)
|
|
81
|
+
if (/^(0x[\da-fA-F]+|\d+)$/.test(host)) {
|
|
82
|
+
const val = host.toLowerCase().startsWith("0x") ? parseInt(host, 16) : parseInt(host, 10);
|
|
83
|
+
if (val >= 0 && val <= 0xffffffff)
|
|
84
|
+
return val >>> 0;
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
// Dotted notation with possible octal/hex octets
|
|
88
|
+
const parts = host.split(".");
|
|
89
|
+
if (parts.length < 2 || parts.length > 4)
|
|
90
|
+
return null;
|
|
91
|
+
const octets = [];
|
|
92
|
+
for (const part of parts) {
|
|
93
|
+
if (!part)
|
|
94
|
+
return null;
|
|
95
|
+
let val;
|
|
96
|
+
if (part.toLowerCase().startsWith("0x")) {
|
|
97
|
+
val = parseInt(part, 16);
|
|
98
|
+
}
|
|
99
|
+
else if (part.startsWith("0") && part.length > 1 && /^[0-7]+$/.test(part)) {
|
|
100
|
+
val = parseInt(part, 8);
|
|
101
|
+
}
|
|
102
|
+
else if (/^\d+$/.test(part)) {
|
|
103
|
+
val = parseInt(part, 10);
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
if (isNaN(val) || val < 0)
|
|
109
|
+
return null;
|
|
110
|
+
octets.push(val);
|
|
111
|
+
}
|
|
112
|
+
// Standard 4-octet form
|
|
113
|
+
if (octets.length === 4) {
|
|
114
|
+
if (octets.some((o) => o > 255))
|
|
115
|
+
return null;
|
|
116
|
+
return ((octets[0] << 24) | (octets[1] << 16) | (octets[2] << 8) | octets[3]) >>> 0;
|
|
117
|
+
}
|
|
118
|
+
// 3-part: a.b.c where c is 16-bit
|
|
119
|
+
if (octets.length === 3) {
|
|
120
|
+
if (octets[0] > 255 || octets[1] > 255 || octets[2] > 0xffff)
|
|
121
|
+
return null;
|
|
122
|
+
return ((octets[0] << 24) | (octets[1] << 16) | octets[2]) >>> 0;
|
|
123
|
+
}
|
|
124
|
+
// 2-part: a.b where b is 24-bit
|
|
125
|
+
if (octets.length === 2) {
|
|
126
|
+
if (octets[0] > 255 || octets[1] > 0xffffff)
|
|
127
|
+
return null;
|
|
128
|
+
return ((octets[0] << 24) | octets[1]) >>> 0;
|
|
129
|
+
}
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Check if an IP address string (v4 or v6) is private/reserved.
|
|
134
|
+
* Exported for use by resolve parameter validation.
|
|
135
|
+
*/
|
|
136
|
+
export function isPrivateIP(ip) {
|
|
137
|
+
// Try IPv4 (including obfuscated forms)
|
|
138
|
+
const ipv4Num = parseObfuscatedIPv4(ip);
|
|
139
|
+
if (ipv4Num !== null)
|
|
140
|
+
return isPrivateIPv4(ipv4Num);
|
|
141
|
+
// Try standard dotted-quad IPv4
|
|
142
|
+
const dotParts = ip.split(".");
|
|
143
|
+
if (dotParts.length === 4 && dotParts.every((p) => /^\d{1,3}$/.test(p))) {
|
|
144
|
+
const num = ipv4ToNum(ip);
|
|
145
|
+
return isPrivateIPv4(num);
|
|
146
|
+
}
|
|
147
|
+
// IPv6
|
|
148
|
+
if (ip.includes(":"))
|
|
149
|
+
return isPrivateIPv6(ip);
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Validates that a URL uses only http:// or https:// schemes and does not
|
|
154
|
+
* target private/reserved IP ranges (SSRF protection).
|
|
155
|
+
*
|
|
156
|
+
* Set environment variable PARE_HTTP_ALLOW_PRIVATE=true to disable
|
|
157
|
+
* private IP blocking (e.g., for local development).
|
|
158
|
+
*/
|
|
159
|
+
export async function assertSafeUrl(url) {
|
|
6
160
|
const trimmed = url.trim();
|
|
7
161
|
if (!trimmed) {
|
|
8
162
|
throw new Error("URL must not be empty.");
|
|
@@ -11,6 +165,106 @@ export function assertSafeUrl(url) {
|
|
|
11
165
|
if (!lower.startsWith("http://") && !lower.startsWith("https://")) {
|
|
12
166
|
throw new Error(`Unsafe URL scheme. Only http:// and https:// are allowed. Got: "${url}"`);
|
|
13
167
|
}
|
|
168
|
+
// Skip private IP checks if opted out
|
|
169
|
+
if (process.env.PARE_HTTP_ALLOW_PRIVATE === "true")
|
|
170
|
+
return;
|
|
171
|
+
let parsed;
|
|
172
|
+
try {
|
|
173
|
+
parsed = new URL(trimmed);
|
|
174
|
+
}
|
|
175
|
+
catch {
|
|
176
|
+
throw new Error(`Invalid URL: "${url}"`);
|
|
177
|
+
}
|
|
178
|
+
const hostname = parsed.hostname;
|
|
179
|
+
// Block known metadata hostnames
|
|
180
|
+
if (BLOCKED_HOSTNAMES.has(hostname.toLowerCase())) {
|
|
181
|
+
throw new Error(`Blocked request to metadata hostname "${hostname}". This is restricted for SSRF protection. ` +
|
|
182
|
+
`Set PARE_HTTP_ALLOW_PRIVATE=true to override.`);
|
|
183
|
+
}
|
|
184
|
+
// Check if hostname is directly an IP address (including obfuscated forms)
|
|
185
|
+
// Remove brackets from IPv6
|
|
186
|
+
const cleanHost = hostname.startsWith("[") ? hostname.slice(1, -1) : hostname;
|
|
187
|
+
// Check obfuscated IPv4 forms directly
|
|
188
|
+
const obfuscatedIP = parseObfuscatedIPv4(cleanHost);
|
|
189
|
+
if (obfuscatedIP !== null && isPrivateIPv4(obfuscatedIP)) {
|
|
190
|
+
throw new Error(`Blocked request to private/reserved IP address "${hostname}". ` +
|
|
191
|
+
`This is restricted for SSRF protection. Set PARE_HTTP_ALLOW_PRIVATE=true to override.`);
|
|
192
|
+
}
|
|
193
|
+
// Check direct IPv6
|
|
194
|
+
if (cleanHost.includes(":") && isPrivateIPv6(cleanHost)) {
|
|
195
|
+
throw new Error(`Blocked request to private/reserved IP address "${hostname}". ` +
|
|
196
|
+
`This is restricted for SSRF protection. Set PARE_HTTP_ALLOW_PRIVATE=true to override.`);
|
|
197
|
+
}
|
|
198
|
+
// DNS resolution check — resolve hostname and check resulting IP
|
|
199
|
+
try {
|
|
200
|
+
const result = await lookup(hostname);
|
|
201
|
+
if (isPrivateIP(result.address)) {
|
|
202
|
+
throw new Error(`Blocked request to "${hostname}" — resolves to private/reserved IP ${result.address}. ` +
|
|
203
|
+
`This is restricted for SSRF protection. Set PARE_HTTP_ALLOW_PRIVATE=true to override.`);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
catch (err) {
|
|
207
|
+
// Re-throw our own SSRF errors
|
|
208
|
+
if (err instanceof Error && err.message.includes("SSRF protection"))
|
|
209
|
+
throw err;
|
|
210
|
+
// DNS resolution failure is not necessarily an error (e.g., offline, custom resolver)
|
|
211
|
+
// Let curl handle it downstream
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Validates that the `resolve` parameter's target IP address is not private/reserved.
|
|
216
|
+
* Format: "host:port:addr" or "host:port:addr,addr2"
|
|
217
|
+
*
|
|
218
|
+
* Blocks DNS rebinding attacks where --resolve is used to redirect
|
|
219
|
+
* requests to private IPs despite the URL appearing safe.
|
|
220
|
+
*/
|
|
221
|
+
export function assertSafeResolve(resolve) {
|
|
222
|
+
if (process.env.PARE_HTTP_ALLOW_PRIVATE === "true")
|
|
223
|
+
return;
|
|
224
|
+
// Format: host:port:addr[,addr2,...]
|
|
225
|
+
const parts = resolve.split(":");
|
|
226
|
+
if (parts.length < 3)
|
|
227
|
+
return; // Let curl handle format errors
|
|
228
|
+
// The addr portion is everything after the second colon (may contain : for IPv6)
|
|
229
|
+
const addrPart = parts.slice(2).join(":");
|
|
230
|
+
// May be comma-separated multiple addresses
|
|
231
|
+
const addrs = addrPart.split(",");
|
|
232
|
+
for (const addr of addrs) {
|
|
233
|
+
const trimmed = addr.trim();
|
|
234
|
+
if (!trimmed)
|
|
235
|
+
continue;
|
|
236
|
+
if (isPrivateIP(trimmed)) {
|
|
237
|
+
throw new Error(`Blocked resolve to private/reserved IP "${trimmed}". ` +
|
|
238
|
+
`The resolve parameter cannot redirect requests to private networks. ` +
|
|
239
|
+
`Set PARE_HTTP_ALLOW_PRIVATE=true to override.`);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Validates that a cookie value is a cookie string (contains '='), not a file path.
|
|
245
|
+
* curl's -b flag reads cookies from a file if the value doesn't contain '='.
|
|
246
|
+
* This prevents arbitrary file read via the cookie parameter.
|
|
247
|
+
*/
|
|
248
|
+
export function assertSafeCookie(cookie) {
|
|
249
|
+
if (!cookie.includes("=")) {
|
|
250
|
+
throw new Error(`Invalid cookie value: must be in "name=value" format (e.g., "session=abc123"). ` +
|
|
251
|
+
`File-based cookie jars are not supported for security reasons.`);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Validates that form values do not use @filepath syntax for file uploads
|
|
256
|
+
* unless explicitly allowed via PARE_HTTP_ALLOW_FILE_UPLOAD=true.
|
|
257
|
+
* curl's -F flag reads file contents when the value starts with '@'.
|
|
258
|
+
*/
|
|
259
|
+
export function assertSafeFormValues(form) {
|
|
260
|
+
if (process.env.PARE_HTTP_ALLOW_FILE_UPLOAD === "true")
|
|
261
|
+
return;
|
|
262
|
+
for (const [key, value] of Object.entries(form)) {
|
|
263
|
+
if (value.startsWith("@")) {
|
|
264
|
+
throw new Error(`Blocked file upload in form field "${key}": value starts with "@" which reads a local file. ` +
|
|
265
|
+
`Set PARE_HTTP_ALLOW_FILE_UPLOAD=true to allow file uploads via form data.`);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
14
268
|
}
|
|
15
269
|
/**
|
|
16
270
|
* Validates that a header key or value does not contain newlines or control characters
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"url-validation.js","sourceRoot":"","sources":["../../src/lib/url-validation.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,
|
|
1
|
+
{"version":3,"file":"url-validation.js","sourceRoot":"","sources":["../../src/lib/url-validation.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/get.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get.d.ts","sourceRoot":"","sources":["../../src/tools/get.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAsBzE,wDAAwD;AACxD,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,
|
|
1
|
+
{"version":3,"file":"get.d.ts","sourceRoot":"","sources":["../../src/tools/get.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAsBzE,wDAAwD;AACxD,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,QAiKhD"}
|
package/dist/tools/get.js
CHANGED
|
@@ -4,14 +4,16 @@ import { curlCmd } from "../lib/curl-runner.js";
|
|
|
4
4
|
import { parseCurlOutput } from "../lib/parsers.js";
|
|
5
5
|
import { formatHttpResponse, schemaResponseMap, compactResponseMap, formatResponseCompact, } from "../lib/formatters.js";
|
|
6
6
|
import { HttpResponseSchema } from "../schemas/index.js";
|
|
7
|
-
import { assertSafeUrl } from "../lib/url-validation.js";
|
|
7
|
+
import { assertSafeUrl, assertSafeResolve } from "../lib/url-validation.js";
|
|
8
8
|
import { buildCurlArgs } from "./request.js";
|
|
9
9
|
const HTTP_VERSIONS = ["1.0", "1.1", "2"];
|
|
10
10
|
/** Registers the `get` tool on the given MCP server. */
|
|
11
11
|
export function registerGetTool(server) {
|
|
12
12
|
server.registerTool("get", {
|
|
13
13
|
title: "HTTP GET",
|
|
14
|
-
description: "Makes an HTTP GET request via curl and returns structured response data. Convenience wrapper for the request tool."
|
|
14
|
+
description: "Makes an HTTP GET request via curl and returns structured response data. Convenience wrapper for the request tool. " +
|
|
15
|
+
"SECURITY: URLs targeting private/reserved IPs are blocked (SSRF protection). " +
|
|
16
|
+
"The proxy parameter routes traffic through an external proxy — use only with trusted proxies.",
|
|
15
17
|
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
16
18
|
inputSchema: {
|
|
17
19
|
url: z
|
|
@@ -63,7 +65,7 @@ export function registerGetTool(server) {
|
|
|
63
65
|
.string()
|
|
64
66
|
.max(INPUT_LIMITS.STRING_MAX)
|
|
65
67
|
.optional()
|
|
66
|
-
.describe("Proxy URL (e.g., http://proxy:8080) (-x)"),
|
|
68
|
+
.describe("Proxy URL (e.g., http://proxy:8080) (-x). SECURITY WARNING: Routes all traffic through this proxy. Only use trusted proxies — a malicious proxy can intercept and modify all request/response data (MitM)."),
|
|
67
69
|
queryParams: z
|
|
68
70
|
.record(z.string().max(INPUT_LIMITS.SHORT_STRING_MAX), z.string().max(INPUT_LIMITS.STRING_MAX))
|
|
69
71
|
.optional()
|
|
@@ -92,13 +94,15 @@ export function registerGetTool(server) {
|
|
|
92
94
|
const separator = url.includes("?") ? "&" : "?";
|
|
93
95
|
finalUrl = `${url}${separator}${params.toString()}`;
|
|
94
96
|
}
|
|
95
|
-
assertSafeUrl(finalUrl);
|
|
97
|
+
await assertSafeUrl(finalUrl);
|
|
96
98
|
if (basicAuth)
|
|
97
99
|
assertNoFlagInjection(basicAuth, "basicAuth");
|
|
98
100
|
if (proxy)
|
|
99
101
|
assertNoFlagInjection(proxy, "proxy");
|
|
100
|
-
if (resolve)
|
|
102
|
+
if (resolve) {
|
|
101
103
|
assertNoFlagInjection(resolve, "resolve");
|
|
104
|
+
assertSafeResolve(resolve);
|
|
105
|
+
}
|
|
102
106
|
const args = buildCurlArgs({
|
|
103
107
|
url: finalUrl,
|
|
104
108
|
method: "GET",
|
package/dist/tools/get.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get.js","sourceRoot":"","sources":["../../src/tools/get.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EACL,yBAAyB,EACzB,qBAAqB,EACrB,YAAY,EACZ,YAAY,EACZ,YAAY,GACb,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,qBAAqB,GACtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"get.js","sourceRoot":"","sources":["../../src/tools/get.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/head.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"head.d.ts","sourceRoot":"","sources":["../../src/tools/head.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAsBzE,yDAAyD;AACzD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,
|
|
1
|
+
{"version":3,"file":"head.d.ts","sourceRoot":"","sources":["../../src/tools/head.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAsBzE,yDAAyD;AACzD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,QAuIjD"}
|
package/dist/tools/head.js
CHANGED
|
@@ -4,14 +4,16 @@ import { curlCmd } from "../lib/curl-runner.js";
|
|
|
4
4
|
import { parseCurlHeadOutput } from "../lib/parsers.js";
|
|
5
5
|
import { formatHttpHeadResponse, schemaHeadResponseMap, compactHeadResponseMap, formatHeadResponseCompact, } from "../lib/formatters.js";
|
|
6
6
|
import { HttpHeadResponseSchema } from "../schemas/index.js";
|
|
7
|
-
import { assertSafeUrl } from "../lib/url-validation.js";
|
|
7
|
+
import { assertSafeUrl, assertSafeResolve } from "../lib/url-validation.js";
|
|
8
8
|
import { buildCurlArgs } from "./request.js";
|
|
9
9
|
const HTTP_VERSIONS = ["1.0", "1.1", "2"];
|
|
10
10
|
/** Registers the `head` tool on the given MCP server. */
|
|
11
11
|
export function registerHeadTool(server) {
|
|
12
12
|
server.registerTool("head", {
|
|
13
13
|
title: "HTTP HEAD",
|
|
14
|
-
description: "Makes an HTTP HEAD request via curl and returns structured response headers (no body). Use to check resource existence, content type, or cache headers."
|
|
14
|
+
description: "Makes an HTTP HEAD request via curl and returns structured response headers (no body). Use to check resource existence, content type, or cache headers. " +
|
|
15
|
+
"SECURITY: URLs targeting private/reserved IPs are blocked (SSRF protection). " +
|
|
16
|
+
"The proxy parameter routes traffic through an external proxy — use only with trusted proxies.",
|
|
15
17
|
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
16
18
|
inputSchema: {
|
|
17
19
|
url: z
|
|
@@ -59,7 +61,7 @@ export function registerHeadTool(server) {
|
|
|
59
61
|
.string()
|
|
60
62
|
.max(INPUT_LIMITS.STRING_MAX)
|
|
61
63
|
.optional()
|
|
62
|
-
.describe("Proxy URL (e.g., http://proxy:8080) (-x)"),
|
|
64
|
+
.describe("Proxy URL (e.g., http://proxy:8080) (-x). SECURITY WARNING: Routes all traffic through this proxy. Only use trusted proxies — a malicious proxy can intercept and modify all request/response data (MitM)."),
|
|
63
65
|
httpVersion: z
|
|
64
66
|
.enum(HTTP_VERSIONS)
|
|
65
67
|
.optional()
|
|
@@ -74,13 +76,15 @@ export function registerHeadTool(server) {
|
|
|
74
76
|
},
|
|
75
77
|
outputSchema: HttpHeadResponseSchema,
|
|
76
78
|
}, async ({ url, headers, timeout, connectTimeout, followRedirects, insecure, retry, basicAuth, proxy, httpVersion, resolve, compact, path, }) => {
|
|
77
|
-
assertSafeUrl(url);
|
|
79
|
+
await assertSafeUrl(url);
|
|
78
80
|
if (basicAuth)
|
|
79
81
|
assertNoFlagInjection(basicAuth, "basicAuth");
|
|
80
82
|
if (proxy)
|
|
81
83
|
assertNoFlagInjection(proxy, "proxy");
|
|
82
|
-
if (resolve)
|
|
84
|
+
if (resolve) {
|
|
83
85
|
assertNoFlagInjection(resolve, "resolve");
|
|
86
|
+
assertSafeResolve(resolve);
|
|
87
|
+
}
|
|
84
88
|
const args = buildCurlArgs({
|
|
85
89
|
url,
|
|
86
90
|
method: "HEAD",
|
package/dist/tools/head.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"head.js","sourceRoot":"","sources":["../../src/tools/head.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EACL,yBAAyB,EACzB,qBAAqB,EACrB,YAAY,EACZ,YAAY,EACZ,YAAY,GACb,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EACL,sBAAsB,EACtB,qBAAqB,EACrB,sBAAsB,EACtB,yBAAyB,GAC1B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"head.js","sourceRoot":"","sources":["../../src/tools/head.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/post.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"post.d.ts","sourceRoot":"","sources":["../../src/tools/post.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAsBzE,yDAAyD;AACzD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,
|
|
1
|
+
{"version":3,"file":"post.d.ts","sourceRoot":"","sources":["../../src/tools/post.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAsBzE,yDAAyD;AACzD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,QAiMjD"}
|
package/dist/tools/post.js
CHANGED
|
@@ -4,14 +4,17 @@ import { curlCmd } from "../lib/curl-runner.js";
|
|
|
4
4
|
import { parseCurlOutput } from "../lib/parsers.js";
|
|
5
5
|
import { formatHttpResponse, schemaResponseMap, compactResponseMap, formatResponseCompact, } from "../lib/formatters.js";
|
|
6
6
|
import { HttpResponseSchema } from "../schemas/index.js";
|
|
7
|
-
import { assertSafeUrl } from "../lib/url-validation.js";
|
|
7
|
+
import { assertSafeUrl, assertSafeFormValues } from "../lib/url-validation.js";
|
|
8
8
|
import { buildCurlArgs } from "./request.js";
|
|
9
9
|
const HTTP_VERSIONS = ["1.0", "1.1", "2"];
|
|
10
10
|
/** Registers the `post` tool on the given MCP server. */
|
|
11
11
|
export function registerPostTool(server) {
|
|
12
12
|
server.registerTool("post", {
|
|
13
13
|
title: "HTTP POST",
|
|
14
|
-
description: "Makes an HTTP POST request via curl and returns structured response data. Convenience wrapper for the request tool with required body."
|
|
14
|
+
description: "Makes an HTTP POST request via curl and returns structured response data. Convenience wrapper for the request tool with required body. " +
|
|
15
|
+
"SECURITY: URLs targeting private/reserved IPs are blocked (SSRF protection). " +
|
|
16
|
+
"File uploads via form @filepath are blocked by default (set PARE_HTTP_ALLOW_FILE_UPLOAD=true to allow). " +
|
|
17
|
+
"The proxy parameter routes traffic through an external proxy — use only with trusted proxies.",
|
|
15
18
|
annotations: { openWorldHint: true },
|
|
16
19
|
inputSchema: {
|
|
17
20
|
url: z
|
|
@@ -77,7 +80,7 @@ export function registerPostTool(server) {
|
|
|
77
80
|
.string()
|
|
78
81
|
.max(INPUT_LIMITS.STRING_MAX)
|
|
79
82
|
.optional()
|
|
80
|
-
.describe("Proxy URL (e.g., http://proxy:8080) (-x)"),
|
|
83
|
+
.describe("Proxy URL (e.g., http://proxy:8080) (-x). SECURITY WARNING: Routes all traffic through this proxy. Only use trusted proxies — a malicious proxy can intercept and modify all request/response data (MitM)."),
|
|
81
84
|
dataUrlencode: z
|
|
82
85
|
.array(z.string().max(INPUT_LIMITS.STRING_MAX))
|
|
83
86
|
.optional()
|
|
@@ -85,7 +88,7 @@ export function registerPostTool(server) {
|
|
|
85
88
|
form: z
|
|
86
89
|
.record(z.string().max(INPUT_LIMITS.SHORT_STRING_MAX), z.string().max(INPUT_LIMITS.STRING_MAX))
|
|
87
90
|
.optional()
|
|
88
|
-
.describe("Multipart form data as key-value pairs (-F). Each pair maps to `-F key=value`.
|
|
91
|
+
.describe("Multipart form data as key-value pairs (-F). Each pair maps to `-F key=value`. File uploads via @filepath are blocked by default — set PARE_HTTP_ALLOW_FILE_UPLOAD=true to allow. When provided, `body` and `contentType` are ignored."),
|
|
89
92
|
httpVersion: z
|
|
90
93
|
.enum(HTTP_VERSIONS)
|
|
91
94
|
.optional()
|
|
@@ -95,7 +98,7 @@ export function registerPostTool(server) {
|
|
|
95
98
|
},
|
|
96
99
|
outputSchema: HttpResponseSchema,
|
|
97
100
|
}, async ({ url, body, headers, contentType, timeout, connectTimeout, followRedirects, preserveMethodOnRedirect, insecure, accept, compressed, basicAuth, proxy, dataUrlencode, form, httpVersion, compact, path, }) => {
|
|
98
|
-
assertSafeUrl(url);
|
|
101
|
+
await assertSafeUrl(url);
|
|
99
102
|
if (accept)
|
|
100
103
|
assertNoFlagInjection(accept, "accept");
|
|
101
104
|
if (basicAuth)
|
|
@@ -111,6 +114,7 @@ export function registerPostTool(server) {
|
|
|
111
114
|
for (const value of Object.values(form)) {
|
|
112
115
|
assertNoFlagInjection(value, "form value");
|
|
113
116
|
}
|
|
117
|
+
assertSafeFormValues(form);
|
|
114
118
|
}
|
|
115
119
|
// When form is provided, don't set Content-Type (curl sets multipart/form-data automatically)
|
|
116
120
|
const mergedHeaders = form
|
package/dist/tools/post.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"post.js","sourceRoot":"","sources":["../../src/tools/post.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EACL,yBAAyB,EACzB,qBAAqB,EACrB,YAAY,EACZ,YAAY,EACZ,YAAY,GACb,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,qBAAqB,GACtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"post.js","sourceRoot":"","sources":["../../src/tools/post.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/tools/request.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/tools/request.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA4BzE,4DAA4D;AAC5D,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,QAoLpD;AAED;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,yFAAyF;IACzF,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,+DAA+D;IAC/D,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,oFAAoF;IACpF,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,oBAAoB,GAAG,MAAM,EAAE,CA0IlE"}
|
package/dist/tools/request.js
CHANGED
|
@@ -4,14 +4,17 @@ import { curlCmd } from "../lib/curl-runner.js";
|
|
|
4
4
|
import { parseCurlOutput, PARE_META_SEPARATOR } from "../lib/parsers.js";
|
|
5
5
|
import { formatHttpResponse, schemaResponseMap, compactResponseMap, formatResponseCompact, } from "../lib/formatters.js";
|
|
6
6
|
import { HttpResponseSchema } from "../schemas/index.js";
|
|
7
|
-
import { assertSafeUrl, assertSafeHeader } from "../lib/url-validation.js";
|
|
7
|
+
import { assertSafeUrl, assertSafeHeader, assertSafeResolve, assertSafeCookie, assertSafeFormValues, } from "../lib/url-validation.js";
|
|
8
8
|
const METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"];
|
|
9
9
|
const HTTP_VERSIONS = ["1.0", "1.1", "2"];
|
|
10
10
|
/** Registers the `request` tool on the given MCP server. */
|
|
11
11
|
export function registerRequestTool(server) {
|
|
12
12
|
server.registerTool("request", {
|
|
13
13
|
title: "HTTP Request",
|
|
14
|
-
description: "Makes an HTTP request via curl and returns structured response data (status, headers, body, timing)."
|
|
14
|
+
description: "Makes an HTTP request via curl and returns structured response data (status, headers, body, timing). " +
|
|
15
|
+
"SECURITY: URLs targeting private/reserved IPs are blocked (SSRF protection). " +
|
|
16
|
+
"The proxy parameter routes traffic through an external proxy — use only with trusted proxies. " +
|
|
17
|
+
"File uploads via form @filepath are blocked by default (set PARE_HTTP_ALLOW_FILE_UPLOAD=true to allow).",
|
|
15
18
|
annotations: { openWorldHint: true },
|
|
16
19
|
inputSchema: {
|
|
17
20
|
url: z
|
|
@@ -31,7 +34,7 @@ export function registerRequestTool(server) {
|
|
|
31
34
|
form: z
|
|
32
35
|
.record(z.string().max(INPUT_LIMITS.SHORT_STRING_MAX), z.string().max(INPUT_LIMITS.STRING_MAX))
|
|
33
36
|
.optional()
|
|
34
|
-
.describe("Multipart form data as key-value pairs (-F). Each pair maps to `-F key=value`.
|
|
37
|
+
.describe("Multipart form data as key-value pairs (-F). Each pair maps to `-F key=value`. File uploads via @filepath are blocked by default — set PARE_HTTP_ALLOW_FILE_UPLOAD=true to allow."),
|
|
35
38
|
timeout: z
|
|
36
39
|
.number()
|
|
37
40
|
.min(1)
|
|
@@ -73,7 +76,7 @@ export function registerRequestTool(server) {
|
|
|
73
76
|
.string()
|
|
74
77
|
.max(INPUT_LIMITS.STRING_MAX)
|
|
75
78
|
.optional()
|
|
76
|
-
.describe("Proxy URL (e.g., http://proxy:8080) (-x)"),
|
|
79
|
+
.describe("Proxy URL (e.g., http://proxy:8080) (-x). SECURITY WARNING: Routes all traffic through this proxy. Only use trusted proxies — a malicious proxy can intercept and modify all request/response data (MitM)."),
|
|
77
80
|
httpVersion: z
|
|
78
81
|
.enum(HTTP_VERSIONS)
|
|
79
82
|
.optional()
|
|
@@ -82,7 +85,7 @@ export function registerRequestTool(server) {
|
|
|
82
85
|
.string()
|
|
83
86
|
.max(INPUT_LIMITS.STRING_MAX)
|
|
84
87
|
.optional()
|
|
85
|
-
.describe("Cookie string
|
|
88
|
+
.describe("Cookie string for session-based APIs (-b). Format: 'name=value; name2=value2'. Must contain '=' — file-based cookie jars are not supported."),
|
|
86
89
|
resolve: z
|
|
87
90
|
.string()
|
|
88
91
|
.max(INPUT_LIMITS.STRING_MAX)
|
|
@@ -93,19 +96,24 @@ export function registerRequestTool(server) {
|
|
|
93
96
|
},
|
|
94
97
|
outputSchema: HttpResponseSchema,
|
|
95
98
|
}, async ({ url, method, headers, body, form, timeout, connectTimeout, followRedirects, insecure, retry, compressed, basicAuth, proxy, httpVersion, cookie, resolve, compact, path, }) => {
|
|
96
|
-
assertSafeUrl(url);
|
|
99
|
+
await assertSafeUrl(url);
|
|
97
100
|
if (basicAuth)
|
|
98
101
|
assertNoFlagInjection(basicAuth, "basicAuth");
|
|
99
102
|
if (proxy)
|
|
100
103
|
assertNoFlagInjection(proxy, "proxy");
|
|
101
|
-
if (cookie)
|
|
104
|
+
if (cookie) {
|
|
102
105
|
assertNoFlagInjection(cookie, "cookie");
|
|
103
|
-
|
|
106
|
+
assertSafeCookie(cookie);
|
|
107
|
+
}
|
|
108
|
+
if (resolve) {
|
|
104
109
|
assertNoFlagInjection(resolve, "resolve");
|
|
110
|
+
assertSafeResolve(resolve);
|
|
111
|
+
}
|
|
105
112
|
if (form) {
|
|
106
113
|
for (const value of Object.values(form)) {
|
|
107
114
|
assertNoFlagInjection(value, "form value");
|
|
108
115
|
}
|
|
116
|
+
assertSafeFormValues(form);
|
|
109
117
|
}
|
|
110
118
|
const args = buildCurlArgs({
|
|
111
119
|
url,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request.js","sourceRoot":"","sources":["../../src/tools/request.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EACL,yBAAyB,EACzB,qBAAqB,EACrB,YAAY,EACZ,YAAY,EACZ,YAAY,GACb,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,qBAAqB,GACtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,
|
|
1
|
+
{"version":3,"file":"request.js","sourceRoot":"","sources":["../../src/tools/request.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@paretools/http",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"mcpName": "io.github.Dave-London/pare-http",
|
|
5
5
|
"description": "MCP server for HTTP — structured request/response data with headers and status for AI agents",
|
|
6
6
|
"license": "MIT",
|
|
@@ -54,10 +54,10 @@
|
|
|
54
54
|
"dependencies": {
|
|
55
55
|
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
56
56
|
"zod": "^4.3.6",
|
|
57
|
-
"@paretools/shared": "0.
|
|
57
|
+
"@paretools/shared": "0.15.0"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
|
-
"@types/node": "^25.
|
|
60
|
+
"@types/node": "^25.4.0",
|
|
61
61
|
"typescript": "^5.7.0",
|
|
62
62
|
"vitest": "^4.0.18",
|
|
63
63
|
"@paretools/tsconfig": "0.0.0"
|