@llmindset/hf-mcp 0.3.3 → 0.3.4
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/network/ip-policy.d.ts.map +1 -1
- package/dist/network/ip-policy.js +39 -3
- package/dist/network/ip-policy.js.map +1 -1
- package/dist/network/ip-policy.test.js +21 -1
- package/dist/network/ip-policy.test.js.map +1 -1
- package/package.json +1 -1
- package/src/network/ip-policy.test.ts +30 -1
- package/src/network/ip-policy.ts +49 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ip-policy.d.ts","sourceRoot":"","sources":["../../src/network/ip-policy.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,sBAAsB;IACtC,wBAAwB,CAAC,EAAE,OAAO,CAAC;CACnC;
|
|
1
|
+
{"version":3,"file":"ip-policy.d.ts","sourceRoot":"","sources":["../../src/network/ip-policy.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,sBAAsB;IACtC,wBAAwB,CAAC,EAAE,OAAO,CAAC;CACnC;AA+KD,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAY1D;AAwBD,wBAAsB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,sBAA2B,GAAG,OAAO,CAAC,IAAI,CAAC,CAsCjH"}
|
|
@@ -1,3 +1,38 @@
|
|
|
1
|
+
const INTERNAL_ADDRESS_HOST_ALLOWLIST_ENV = 'ALLOW_INTERNAL_ADDRESS_HOSTS';
|
|
2
|
+
function normalizeHostname(hostname) {
|
|
3
|
+
return hostname.trim().toLowerCase().replace(/\.+$/, '');
|
|
4
|
+
}
|
|
5
|
+
function getInternalAddressHostAllowlist() {
|
|
6
|
+
const raw = process.env[INTERNAL_ADDRESS_HOST_ALLOWLIST_ENV];
|
|
7
|
+
if (!raw) {
|
|
8
|
+
return [];
|
|
9
|
+
}
|
|
10
|
+
return raw
|
|
11
|
+
.split(',')
|
|
12
|
+
.map((entry) => normalizeHostname(entry))
|
|
13
|
+
.filter((entry) => entry.length > 0);
|
|
14
|
+
}
|
|
15
|
+
function hostnameMatchesPattern(hostname, pattern) {
|
|
16
|
+
if (pattern.startsWith('*.')) {
|
|
17
|
+
const baseDomain = pattern.slice(2);
|
|
18
|
+
if (!baseDomain) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
return hostname === baseDomain || hostname.endsWith(`.${baseDomain}`);
|
|
22
|
+
}
|
|
23
|
+
return hostname === pattern;
|
|
24
|
+
}
|
|
25
|
+
function isInternalAddressAllowedForHostname(hostname) {
|
|
26
|
+
const normalizedHostname = normalizeHostname(hostname);
|
|
27
|
+
if (!normalizedHostname) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
const allowlist = getInternalAddressHostAllowlist();
|
|
31
|
+
if (allowlist.length === 0) {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
return allowlist.some((pattern) => hostnameMatchesPattern(normalizedHostname, pattern));
|
|
35
|
+
}
|
|
1
36
|
function normalizeIpLiteral(host) {
|
|
2
37
|
if (host.startsWith('[') && host.endsWith(']')) {
|
|
3
38
|
return host.slice(1, -1);
|
|
@@ -133,10 +168,11 @@ function detectIpVersion(candidate) {
|
|
|
133
168
|
}
|
|
134
169
|
export async function assertExternalAddress(hostname, options = {}) {
|
|
135
170
|
const { allowDnsRebindMitigation = true } = options;
|
|
136
|
-
const normalized = hostname
|
|
171
|
+
const normalized = normalizeHostname(hostname);
|
|
137
172
|
if (!normalized) {
|
|
138
173
|
throw new Error('Hostname is required for external address check');
|
|
139
174
|
}
|
|
175
|
+
const allowInternalAddress = isInternalAddressAllowedForHostname(normalized);
|
|
140
176
|
const ipLiteral = normalizeIpLiteral(normalized);
|
|
141
177
|
const ipVersion = detectIpVersion(ipLiteral);
|
|
142
178
|
if (ipVersion !== 0) {
|
|
@@ -150,14 +186,14 @@ export async function assertExternalAddress(hostname, options = {}) {
|
|
|
150
186
|
throw new Error(`No DNS records found for hostname: ${normalized}`);
|
|
151
187
|
}
|
|
152
188
|
for (const address of firstLookup) {
|
|
153
|
-
if (isIpInternalOrReserved(address)) {
|
|
189
|
+
if (isIpInternalOrReserved(address) && !allowInternalAddress) {
|
|
154
190
|
throw new Error(`Blocked internal or reserved address for hostname ${normalized}: ${address}`);
|
|
155
191
|
}
|
|
156
192
|
}
|
|
157
193
|
if (allowDnsRebindMitigation) {
|
|
158
194
|
const secondLookup = await lookupAll(normalized);
|
|
159
195
|
for (const address of secondLookup) {
|
|
160
|
-
if (isIpInternalOrReserved(address)) {
|
|
196
|
+
if (isIpInternalOrReserved(address) && !allowInternalAddress) {
|
|
161
197
|
throw new Error(`Blocked internal or reserved address for hostname ${normalized}: ${address}`);
|
|
162
198
|
}
|
|
163
199
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ip-policy.js","sourceRoot":"","sources":["../../src/network/ip-policy.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"ip-policy.js","sourceRoot":"","sources":["../../src/network/ip-policy.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,16 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
1
|
+
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
2
2
|
import { assertExternalAddress, isIpInternalOrReserved } from './ip-policy.js';
|
|
3
|
+
const { lookupMock } = vi.hoisted(() => ({
|
|
4
|
+
lookupMock: vi.fn(),
|
|
5
|
+
}));
|
|
6
|
+
vi.mock('node:dns/promises', () => ({
|
|
7
|
+
lookup: lookupMock,
|
|
8
|
+
}));
|
|
3
9
|
describe('ip-policy', () => {
|
|
10
|
+
afterEach(() => {
|
|
11
|
+
lookupMock.mockReset();
|
|
12
|
+
delete process.env.ALLOW_INTERNAL_ADDRESS_HOSTS;
|
|
13
|
+
});
|
|
4
14
|
it('classifies internal/reserved IPv4 ranges', () => {
|
|
5
15
|
expect(isIpInternalOrReserved('127.0.0.1')).toBe(true);
|
|
6
16
|
expect(isIpInternalOrReserved('10.1.2.3')).toBe(true);
|
|
@@ -22,5 +32,15 @@ describe('ip-policy', () => {
|
|
|
22
32
|
it('allows external literal addresses in assertExternalAddress', async () => {
|
|
23
33
|
await expect(assertExternalAddress('8.8.8.8')).resolves.toBeUndefined();
|
|
24
34
|
});
|
|
35
|
+
it('blocks hostnames resolving to internal addresses by default', async () => {
|
|
36
|
+
lookupMock.mockResolvedValue([{ address: '10.0.246.93' }]);
|
|
37
|
+
await expect(assertExternalAddress('huggingface.co')).rejects.toThrow('Blocked internal or reserved address for hostname huggingface.co: 10.0.246.93');
|
|
38
|
+
});
|
|
39
|
+
it('allows allowlisted hostnames to resolve to internal addresses', async () => {
|
|
40
|
+
process.env.ALLOW_INTERNAL_ADDRESS_HOSTS = 'huggingface.co,*.hf.space';
|
|
41
|
+
lookupMock.mockResolvedValue([{ address: '10.0.246.93' }]);
|
|
42
|
+
await expect(assertExternalAddress('huggingface.co')).resolves.toBeUndefined();
|
|
43
|
+
await expect(assertExternalAddress('demo.hf.space')).resolves.toBeUndefined();
|
|
44
|
+
});
|
|
25
45
|
});
|
|
26
46
|
//# sourceMappingURL=ip-policy.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ip-policy.test.js","sourceRoot":"","sources":["../../src/network/ip-policy.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"ip-policy.test.js","sourceRoot":"","sources":["../../src/network/ip-policy.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,20 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
1
|
+
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
2
2
|
import { assertExternalAddress, isIpInternalOrReserved } from './ip-policy.js';
|
|
3
3
|
|
|
4
|
+
const { lookupMock } = vi.hoisted(() => ({
|
|
5
|
+
lookupMock: vi.fn(),
|
|
6
|
+
}));
|
|
7
|
+
|
|
8
|
+
vi.mock('node:dns/promises', () => ({
|
|
9
|
+
lookup: lookupMock,
|
|
10
|
+
}));
|
|
11
|
+
|
|
4
12
|
describe('ip-policy', () => {
|
|
13
|
+
afterEach(() => {
|
|
14
|
+
lookupMock.mockReset();
|
|
15
|
+
delete process.env.ALLOW_INTERNAL_ADDRESS_HOSTS;
|
|
16
|
+
});
|
|
17
|
+
|
|
5
18
|
it('classifies internal/reserved IPv4 ranges', () => {
|
|
6
19
|
expect(isIpInternalOrReserved('127.0.0.1')).toBe(true);
|
|
7
20
|
expect(isIpInternalOrReserved('10.1.2.3')).toBe(true);
|
|
@@ -26,4 +39,20 @@ describe('ip-policy', () => {
|
|
|
26
39
|
it('allows external literal addresses in assertExternalAddress', async () => {
|
|
27
40
|
await expect(assertExternalAddress('8.8.8.8')).resolves.toBeUndefined();
|
|
28
41
|
});
|
|
42
|
+
|
|
43
|
+
it('blocks hostnames resolving to internal addresses by default', async () => {
|
|
44
|
+
lookupMock.mockResolvedValue([{ address: '10.0.246.93' }]);
|
|
45
|
+
|
|
46
|
+
await expect(assertExternalAddress('huggingface.co')).rejects.toThrow(
|
|
47
|
+
'Blocked internal or reserved address for hostname huggingface.co: 10.0.246.93'
|
|
48
|
+
);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('allows allowlisted hostnames to resolve to internal addresses', async () => {
|
|
52
|
+
process.env.ALLOW_INTERNAL_ADDRESS_HOSTS = 'huggingface.co,*.hf.space';
|
|
53
|
+
lookupMock.mockResolvedValue([{ address: '10.0.246.93' }]);
|
|
54
|
+
|
|
55
|
+
await expect(assertExternalAddress('huggingface.co')).resolves.toBeUndefined();
|
|
56
|
+
await expect(assertExternalAddress('demo.hf.space')).resolves.toBeUndefined();
|
|
57
|
+
});
|
|
29
58
|
});
|
package/src/network/ip-policy.ts
CHANGED
|
@@ -2,6 +2,50 @@ export interface ExternalAddressOptions {
|
|
|
2
2
|
allowDnsRebindMitigation?: boolean;
|
|
3
3
|
}
|
|
4
4
|
|
|
5
|
+
const INTERNAL_ADDRESS_HOST_ALLOWLIST_ENV = 'ALLOW_INTERNAL_ADDRESS_HOSTS';
|
|
6
|
+
|
|
7
|
+
function normalizeHostname(hostname: string): string {
|
|
8
|
+
return hostname.trim().toLowerCase().replace(/\.+$/, '');
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function getInternalAddressHostAllowlist(): string[] {
|
|
12
|
+
const raw = process.env[INTERNAL_ADDRESS_HOST_ALLOWLIST_ENV];
|
|
13
|
+
if (!raw) {
|
|
14
|
+
return [];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return raw
|
|
18
|
+
.split(',')
|
|
19
|
+
.map((entry) => normalizeHostname(entry))
|
|
20
|
+
.filter((entry) => entry.length > 0);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function hostnameMatchesPattern(hostname: string, pattern: string): boolean {
|
|
24
|
+
if (pattern.startsWith('*.')) {
|
|
25
|
+
const baseDomain = pattern.slice(2);
|
|
26
|
+
if (!baseDomain) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
return hostname === baseDomain || hostname.endsWith(`.${baseDomain}`);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return hostname === pattern;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function isInternalAddressAllowedForHostname(hostname: string): boolean {
|
|
36
|
+
const normalizedHostname = normalizeHostname(hostname);
|
|
37
|
+
if (!normalizedHostname) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const allowlist = getInternalAddressHostAllowlist();
|
|
42
|
+
if (allowlist.length === 0) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return allowlist.some((pattern) => hostnameMatchesPattern(normalizedHostname, pattern));
|
|
47
|
+
}
|
|
48
|
+
|
|
5
49
|
function normalizeIpLiteral(host: string): string {
|
|
6
50
|
if (host.startsWith('[') && host.endsWith(']')) {
|
|
7
51
|
return host.slice(1, -1);
|
|
@@ -169,12 +213,14 @@ function detectIpVersion(candidate: string): 0 | 4 | 6 {
|
|
|
169
213
|
|
|
170
214
|
export async function assertExternalAddress(hostname: string, options: ExternalAddressOptions = {}): Promise<void> {
|
|
171
215
|
const { allowDnsRebindMitigation = true } = options;
|
|
172
|
-
const normalized = hostname
|
|
216
|
+
const normalized = normalizeHostname(hostname);
|
|
173
217
|
|
|
174
218
|
if (!normalized) {
|
|
175
219
|
throw new Error('Hostname is required for external address check');
|
|
176
220
|
}
|
|
177
221
|
|
|
222
|
+
const allowInternalAddress = isInternalAddressAllowedForHostname(normalized);
|
|
223
|
+
|
|
178
224
|
const ipLiteral = normalizeIpLiteral(normalized);
|
|
179
225
|
const ipVersion = detectIpVersion(ipLiteral);
|
|
180
226
|
if (ipVersion !== 0) {
|
|
@@ -190,7 +236,7 @@ export async function assertExternalAddress(hostname: string, options: ExternalA
|
|
|
190
236
|
}
|
|
191
237
|
|
|
192
238
|
for (const address of firstLookup) {
|
|
193
|
-
if (isIpInternalOrReserved(address)) {
|
|
239
|
+
if (isIpInternalOrReserved(address) && !allowInternalAddress) {
|
|
194
240
|
throw new Error(`Blocked internal or reserved address for hostname ${normalized}: ${address}`);
|
|
195
241
|
}
|
|
196
242
|
}
|
|
@@ -198,7 +244,7 @@ export async function assertExternalAddress(hostname: string, options: ExternalA
|
|
|
198
244
|
if (allowDnsRebindMitigation) {
|
|
199
245
|
const secondLookup = await lookupAll(normalized);
|
|
200
246
|
for (const address of secondLookup) {
|
|
201
|
-
if (isIpInternalOrReserved(address)) {
|
|
247
|
+
if (isIpInternalOrReserved(address) && !allowInternalAddress) {
|
|
202
248
|
throw new Error(`Blocked internal or reserved address for hostname ${normalized}: ${address}`);
|
|
203
249
|
}
|
|
204
250
|
}
|