@apidevtools/json-schema-ref-parser 13.0.5 → 14.0.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/lib/index.d.ts +2 -1
- package/dist/lib/index.js +3 -1
- package/dist/lib/resolvers/http.js +5 -1
- package/dist/lib/types/index.d.ts +4 -0
- package/dist/lib/util/url.d.ts +7 -0
- package/dist/lib/util/url.js +147 -0
- package/lib/index.ts +2 -0
- package/lib/resolvers/http.ts +6 -1
- package/lib/types/index.ts +5 -0
- package/lib/util/url.ts +171 -0
- package/package.json +7 -7
package/dist/lib/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { JSONParserError, InvalidPointerError, MissingPointerError, ResolverErro
|
|
|
5
5
|
import type { ParserOptions } from "./options.js";
|
|
6
6
|
import { getJsonSchemaRefParserDefaultOptions } from "./options.js";
|
|
7
7
|
import type { $RefsCallback, JSONSchema, SchemaCallback, FileInfo, Plugin, ResolverOptions, HTTPResolverOptions } from "./types/index.js";
|
|
8
|
+
import { isUnsafeUrl } from "./util/url.js";
|
|
8
9
|
export type RefParserSchema = string | JSONSchema;
|
|
9
10
|
/**
|
|
10
11
|
* This class parses a JSON schema, builds a map of its JSON references and their resolved values,
|
|
@@ -159,4 +160,4 @@ export declare const parse: typeof $RefParser.parse;
|
|
|
159
160
|
export declare const resolve: typeof $RefParser.resolve;
|
|
160
161
|
export declare const bundle: typeof $RefParser.bundle;
|
|
161
162
|
export declare const dereference: typeof $RefParser.dereference;
|
|
162
|
-
export { UnmatchedResolverError, JSONParserError, JSONSchema, InvalidPointerError, MissingPointerError, ResolverError, ParserError, UnmatchedParserError, ParserOptions, $RefsCallback, isHandledError, JSONParserErrorGroup, SchemaCallback, FileInfo, Plugin, ResolverOptions, HTTPResolverOptions, _dereference as dereferenceInternal, normalizeArgs as jsonSchemaParserNormalizeArgs, getJsonSchemaRefParserDefaultOptions, $Refs, };
|
|
163
|
+
export { UnmatchedResolverError, JSONParserError, JSONSchema, InvalidPointerError, MissingPointerError, ResolverError, ParserError, UnmatchedParserError, ParserOptions, $RefsCallback, isHandledError, JSONParserErrorGroup, SchemaCallback, FileInfo, Plugin, ResolverOptions, HTTPResolverOptions, _dereference as dereferenceInternal, normalizeArgs as jsonSchemaParserNormalizeArgs, getJsonSchemaRefParserDefaultOptions, $Refs, isUnsafeUrl, };
|
package/dist/lib/index.js
CHANGED
|
@@ -36,7 +36,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
36
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.$Refs = exports.getJsonSchemaRefParserDefaultOptions = exports.jsonSchemaParserNormalizeArgs = exports.dereferenceInternal = exports.JSONParserErrorGroup = exports.isHandledError = exports.UnmatchedParserError = exports.ParserError = exports.ResolverError = exports.MissingPointerError = exports.InvalidPointerError = exports.JSONParserError = exports.UnmatchedResolverError = exports.dereference = exports.bundle = exports.resolve = exports.parse = exports.$RefParser = void 0;
|
|
39
|
+
exports.isUnsafeUrl = exports.$Refs = exports.getJsonSchemaRefParserDefaultOptions = exports.jsonSchemaParserNormalizeArgs = exports.dereferenceInternal = exports.JSONParserErrorGroup = exports.isHandledError = exports.UnmatchedParserError = exports.ParserError = exports.ResolverError = exports.MissingPointerError = exports.InvalidPointerError = exports.JSONParserError = exports.UnmatchedResolverError = exports.dereference = exports.bundle = exports.resolve = exports.parse = exports.$RefParser = void 0;
|
|
40
40
|
const refs_js_1 = __importDefault(require("./refs.js"));
|
|
41
41
|
exports.$Refs = refs_js_1.default;
|
|
42
42
|
const parse_js_1 = __importDefault(require("./parse.js"));
|
|
@@ -60,6 +60,8 @@ Object.defineProperty(exports, "JSONParserErrorGroup", { enumerable: true, get:
|
|
|
60
60
|
const maybe_js_1 = __importDefault(require("./util/maybe.js"));
|
|
61
61
|
const options_js_1 = require("./options.js");
|
|
62
62
|
Object.defineProperty(exports, "getJsonSchemaRefParserDefaultOptions", { enumerable: true, get: function () { return options_js_1.getJsonSchemaRefParserDefaultOptions; } });
|
|
63
|
+
const url_js_1 = require("./util/url.js");
|
|
64
|
+
Object.defineProperty(exports, "isUnsafeUrl", { enumerable: true, get: function () { return url_js_1.isUnsafeUrl; } });
|
|
63
65
|
/**
|
|
64
66
|
* This class parses a JSON schema, builds a map of its JSON references and their resolved values,
|
|
65
67
|
* and provides methods for traversing, manipulating, and dereferencing those references.
|
|
@@ -64,13 +64,17 @@ exports.default = {
|
|
|
64
64
|
* Set this to `true` if you're downloading files from a CORS-enabled server that requires authentication
|
|
65
65
|
*/
|
|
66
66
|
withCredentials: false,
|
|
67
|
+
/**
|
|
68
|
+
* Set this to `false` if you want to allow unsafe URLs (e.g., `127.0.0.1`, localhost, and other internal URLs).
|
|
69
|
+
*/
|
|
70
|
+
safeUrlResolver: true,
|
|
67
71
|
/**
|
|
68
72
|
* Determines whether this resolver can read a given file reference.
|
|
69
73
|
* Resolvers that return true will be tried in order, until one successfully resolves the file.
|
|
70
74
|
* Resolvers that return false will not be given a chance to resolve the file.
|
|
71
75
|
*/
|
|
72
76
|
canRead(file) {
|
|
73
|
-
return url.isHttp(file.url);
|
|
77
|
+
return url.isHttp(file.url) && (!this.safeUrlResolver || !url.isUnsafeUrl(file.url));
|
|
74
78
|
},
|
|
75
79
|
/**
|
|
76
80
|
* Reads the given URL and returns its raw contents as a Buffer.
|
|
@@ -25,6 +25,10 @@ export interface HTTPResolverOptions<S extends object = JSONSchema> extends Part
|
|
|
25
25
|
* Set this to `true` if you're downloading files from a CORS-enabled server that requires authentication
|
|
26
26
|
*/
|
|
27
27
|
withCredentials?: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Set this to `false` if you want to allow unsafe URLs (e.g., `127.0.0.1`, localhost, and other internal URLs).
|
|
30
|
+
*/
|
|
31
|
+
safeUrlResolver: true;
|
|
28
32
|
}
|
|
29
33
|
/**
|
|
30
34
|
* JSON Schema `$Ref` Parser comes with built-in resolvers for HTTP and HTTPS URLs, as well as local filesystem paths (when running in Node.js). You can add your own custom resolvers to support additional protocols, or even replace any of the built-in resolvers with your own custom implementation.
|
package/dist/lib/util/url.d.ts
CHANGED
|
@@ -55,6 +55,13 @@ export declare function stripHash(path?: string | undefined): string;
|
|
|
55
55
|
* @returns
|
|
56
56
|
*/
|
|
57
57
|
export declare function isHttp(path: string): boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Determines whether the given url is an unsafe or internal url.
|
|
60
|
+
*
|
|
61
|
+
* @param path - The URL or path to check
|
|
62
|
+
* @returns true if the URL is unsafe/internal, false otherwise
|
|
63
|
+
*/
|
|
64
|
+
export declare function isUnsafeUrl(path: string): boolean;
|
|
58
65
|
/**
|
|
59
66
|
* Determines whether the given path is a filesystem path.
|
|
60
67
|
* This includes "file://" URLs.
|
package/dist/lib/util/url.js
CHANGED
|
@@ -45,6 +45,7 @@ exports.stripQuery = stripQuery;
|
|
|
45
45
|
exports.getHash = getHash;
|
|
46
46
|
exports.stripHash = stripHash;
|
|
47
47
|
exports.isHttp = isHttp;
|
|
48
|
+
exports.isUnsafeUrl = isUnsafeUrl;
|
|
48
49
|
exports.isFileSystemPath = isFileSystemPath;
|
|
49
50
|
exports.fromFileSystemPath = fromFileSystemPath;
|
|
50
51
|
exports.toFileSystemPath = toFileSystemPath;
|
|
@@ -209,6 +210,152 @@ function isHttp(path) {
|
|
|
209
210
|
return false;
|
|
210
211
|
}
|
|
211
212
|
}
|
|
213
|
+
/**
|
|
214
|
+
* Determines whether the given url is an unsafe or internal url.
|
|
215
|
+
*
|
|
216
|
+
* @param path - The URL or path to check
|
|
217
|
+
* @returns true if the URL is unsafe/internal, false otherwise
|
|
218
|
+
*/
|
|
219
|
+
function isUnsafeUrl(path) {
|
|
220
|
+
if (!path || typeof path !== "string") {
|
|
221
|
+
return true;
|
|
222
|
+
}
|
|
223
|
+
// Trim whitespace and convert to lowercase for comparison
|
|
224
|
+
const normalizedPath = path.trim().toLowerCase();
|
|
225
|
+
// Empty or just whitespace
|
|
226
|
+
if (!normalizedPath) {
|
|
227
|
+
return true;
|
|
228
|
+
}
|
|
229
|
+
// JavaScript protocols
|
|
230
|
+
if (normalizedPath.startsWith("javascript:") ||
|
|
231
|
+
normalizedPath.startsWith("vbscript:") ||
|
|
232
|
+
normalizedPath.startsWith("data:")) {
|
|
233
|
+
return true;
|
|
234
|
+
}
|
|
235
|
+
// File protocol
|
|
236
|
+
if (normalizedPath.startsWith("file:")) {
|
|
237
|
+
return true;
|
|
238
|
+
}
|
|
239
|
+
// if we're in the browser, we assume that it is safe
|
|
240
|
+
if (typeof window !== "undefined" && window.location && window.location.href) {
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
// Local/internal network addresses
|
|
244
|
+
const localPatterns = [
|
|
245
|
+
// Localhost variations
|
|
246
|
+
"localhost",
|
|
247
|
+
"127.0.0.1",
|
|
248
|
+
"::1",
|
|
249
|
+
// Private IP ranges (RFC 1918)
|
|
250
|
+
"10.",
|
|
251
|
+
"172.16.",
|
|
252
|
+
"172.17.",
|
|
253
|
+
"172.18.",
|
|
254
|
+
"172.19.",
|
|
255
|
+
"172.20.",
|
|
256
|
+
"172.21.",
|
|
257
|
+
"172.22.",
|
|
258
|
+
"172.23.",
|
|
259
|
+
"172.24.",
|
|
260
|
+
"172.25.",
|
|
261
|
+
"172.26.",
|
|
262
|
+
"172.27.",
|
|
263
|
+
"172.28.",
|
|
264
|
+
"172.29.",
|
|
265
|
+
"172.30.",
|
|
266
|
+
"172.31.",
|
|
267
|
+
"192.168.",
|
|
268
|
+
// Link-local addresses
|
|
269
|
+
"169.254.",
|
|
270
|
+
// Internal domains
|
|
271
|
+
".local",
|
|
272
|
+
".internal",
|
|
273
|
+
".intranet",
|
|
274
|
+
".corp",
|
|
275
|
+
".home",
|
|
276
|
+
".lan",
|
|
277
|
+
];
|
|
278
|
+
try {
|
|
279
|
+
// Try to parse as URL
|
|
280
|
+
const url = new URL(normalizedPath.startsWith("//") ? "http:" + normalizedPath : normalizedPath);
|
|
281
|
+
const hostname = url.hostname.toLowerCase();
|
|
282
|
+
// Check against local patterns
|
|
283
|
+
for (const pattern of localPatterns) {
|
|
284
|
+
if (hostname === pattern || hostname.startsWith(pattern) || hostname.endsWith(pattern)) {
|
|
285
|
+
return true;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
// Check for IP addresses in private ranges
|
|
289
|
+
if (isPrivateIP(hostname)) {
|
|
290
|
+
return true;
|
|
291
|
+
}
|
|
292
|
+
// Check for non-standard ports that might indicate internal services
|
|
293
|
+
const port = url.port;
|
|
294
|
+
if (port && isInternalPort(parseInt(port))) {
|
|
295
|
+
return true;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
catch (e) {
|
|
299
|
+
// If URL parsing fails, check if it's a relative path or contains suspicious patterns
|
|
300
|
+
// Relative paths starting with / are generally safe for same-origin
|
|
301
|
+
if (normalizedPath.startsWith("/") && !normalizedPath.startsWith("//")) {
|
|
302
|
+
return false;
|
|
303
|
+
}
|
|
304
|
+
// Check for localhost patterns in non-URL strings
|
|
305
|
+
for (const pattern of localPatterns) {
|
|
306
|
+
if (normalizedPath.includes(pattern)) {
|
|
307
|
+
return true;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
return false;
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Helper function to check if an IP address is in a private range
|
|
315
|
+
*/
|
|
316
|
+
function isPrivateIP(ip) {
|
|
317
|
+
const ipRegex = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
|
|
318
|
+
const match = ip.match(ipRegex);
|
|
319
|
+
if (!match) {
|
|
320
|
+
return false;
|
|
321
|
+
}
|
|
322
|
+
const [, a, b, c, d] = match.map(Number);
|
|
323
|
+
// Validate IP format
|
|
324
|
+
if (a > 255 || b > 255 || c > 255 || d > 255) {
|
|
325
|
+
return false;
|
|
326
|
+
}
|
|
327
|
+
// Private IP ranges
|
|
328
|
+
return (a === 10 || a === 127 || (a === 172 && b >= 16 && b <= 31) || (a === 192 && b === 168) || (a === 169 && b === 254) // Link-local
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Helper function to check if a port is typically used for internal services
|
|
333
|
+
*/
|
|
334
|
+
function isInternalPort(port) {
|
|
335
|
+
const internalPorts = [
|
|
336
|
+
22, // SSH
|
|
337
|
+
23, // Telnet
|
|
338
|
+
25, // SMTP
|
|
339
|
+
53, // DNS
|
|
340
|
+
135, // RPC
|
|
341
|
+
139, // NetBIOS
|
|
342
|
+
445, // SMB
|
|
343
|
+
993, // IMAPS
|
|
344
|
+
995, // POP3S
|
|
345
|
+
1433, // SQL Server
|
|
346
|
+
1521, // Oracle
|
|
347
|
+
3306, // MySQL
|
|
348
|
+
3389, // RDP
|
|
349
|
+
5432, // PostgreSQL
|
|
350
|
+
5900, // VNC
|
|
351
|
+
6379, // Redis
|
|
352
|
+
8080, // Common internal web
|
|
353
|
+
8443, // Common internal HTTPS
|
|
354
|
+
9200, // Elasticsearch
|
|
355
|
+
27017, // MongoDB
|
|
356
|
+
];
|
|
357
|
+
return internalPorts.includes(port);
|
|
358
|
+
}
|
|
212
359
|
/**
|
|
213
360
|
* Determines whether the given path is a filesystem path.
|
|
214
361
|
* This includes "file://" URLs.
|
package/lib/index.ts
CHANGED
|
@@ -28,6 +28,7 @@ import type {
|
|
|
28
28
|
ResolverOptions,
|
|
29
29
|
HTTPResolverOptions,
|
|
30
30
|
} from "./types/index.js";
|
|
31
|
+
import { isUnsafeUrl } from "./util/url.js";
|
|
31
32
|
|
|
32
33
|
export type RefParserSchema = string | JSONSchema;
|
|
33
34
|
|
|
@@ -439,4 +440,5 @@ export {
|
|
|
439
440
|
normalizeArgs as jsonSchemaParserNormalizeArgs,
|
|
440
441
|
getJsonSchemaRefParserDefaultOptions,
|
|
441
442
|
$Refs,
|
|
443
|
+
isUnsafeUrl,
|
|
442
444
|
};
|
package/lib/resolvers/http.ts
CHANGED
|
@@ -36,13 +36,18 @@ export default {
|
|
|
36
36
|
*/
|
|
37
37
|
withCredentials: false,
|
|
38
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Set this to `false` if you want to allow unsafe URLs (e.g., `127.0.0.1`, localhost, and other internal URLs).
|
|
41
|
+
*/
|
|
42
|
+
safeUrlResolver: true,
|
|
43
|
+
|
|
39
44
|
/**
|
|
40
45
|
* Determines whether this resolver can read a given file reference.
|
|
41
46
|
* Resolvers that return true will be tried in order, until one successfully resolves the file.
|
|
42
47
|
* Resolvers that return false will not be given a chance to resolve the file.
|
|
43
48
|
*/
|
|
44
49
|
canRead(file: FileInfo) {
|
|
45
|
-
return url.isHttp(file.url);
|
|
50
|
+
return url.isHttp(file.url) && (!this.safeUrlResolver || !url.isUnsafeUrl(file.url));
|
|
46
51
|
},
|
|
47
52
|
|
|
48
53
|
/**
|
package/lib/types/index.ts
CHANGED
|
@@ -41,6 +41,11 @@ export interface HTTPResolverOptions<S extends object = JSONSchema> extends Part
|
|
|
41
41
|
* Set this to `true` if you're downloading files from a CORS-enabled server that requires authentication
|
|
42
42
|
*/
|
|
43
43
|
withCredentials?: boolean;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Set this to `false` if you want to allow unsafe URLs (e.g., `127.0.0.1`, localhost, and other internal URLs).
|
|
47
|
+
*/
|
|
48
|
+
safeUrlResolver: true;
|
|
44
49
|
}
|
|
45
50
|
|
|
46
51
|
/**
|
package/lib/util/url.ts
CHANGED
|
@@ -167,7 +167,178 @@ export function isHttp(path: string) {
|
|
|
167
167
|
return false;
|
|
168
168
|
}
|
|
169
169
|
}
|
|
170
|
+
/**
|
|
171
|
+
* Determines whether the given url is an unsafe or internal url.
|
|
172
|
+
*
|
|
173
|
+
* @param path - The URL or path to check
|
|
174
|
+
* @returns true if the URL is unsafe/internal, false otherwise
|
|
175
|
+
*/
|
|
176
|
+
export function isUnsafeUrl(path: string): boolean {
|
|
177
|
+
if (!path || typeof path !== "string") {
|
|
178
|
+
return true;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Trim whitespace and convert to lowercase for comparison
|
|
182
|
+
const normalizedPath = path.trim().toLowerCase();
|
|
170
183
|
|
|
184
|
+
// Empty or just whitespace
|
|
185
|
+
if (!normalizedPath) {
|
|
186
|
+
return true;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// JavaScript protocols
|
|
190
|
+
if (
|
|
191
|
+
normalizedPath.startsWith("javascript:") ||
|
|
192
|
+
normalizedPath.startsWith("vbscript:") ||
|
|
193
|
+
normalizedPath.startsWith("data:")
|
|
194
|
+
) {
|
|
195
|
+
return true;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// File protocol
|
|
199
|
+
if (normalizedPath.startsWith("file:")) {
|
|
200
|
+
return true;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// if we're in the browser, we assume that it is safe
|
|
204
|
+
if (typeof window !== "undefined" && window.location && window.location.href) {
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Local/internal network addresses
|
|
209
|
+
const localPatterns = [
|
|
210
|
+
// Localhost variations
|
|
211
|
+
"localhost",
|
|
212
|
+
"127.0.0.1",
|
|
213
|
+
"::1",
|
|
214
|
+
|
|
215
|
+
// Private IP ranges (RFC 1918)
|
|
216
|
+
"10.",
|
|
217
|
+
"172.16.",
|
|
218
|
+
"172.17.",
|
|
219
|
+
"172.18.",
|
|
220
|
+
"172.19.",
|
|
221
|
+
"172.20.",
|
|
222
|
+
"172.21.",
|
|
223
|
+
"172.22.",
|
|
224
|
+
"172.23.",
|
|
225
|
+
"172.24.",
|
|
226
|
+
"172.25.",
|
|
227
|
+
"172.26.",
|
|
228
|
+
"172.27.",
|
|
229
|
+
"172.28.",
|
|
230
|
+
"172.29.",
|
|
231
|
+
"172.30.",
|
|
232
|
+
"172.31.",
|
|
233
|
+
"192.168.",
|
|
234
|
+
|
|
235
|
+
// Link-local addresses
|
|
236
|
+
"169.254.",
|
|
237
|
+
|
|
238
|
+
// Internal domains
|
|
239
|
+
".local",
|
|
240
|
+
".internal",
|
|
241
|
+
".intranet",
|
|
242
|
+
".corp",
|
|
243
|
+
".home",
|
|
244
|
+
".lan",
|
|
245
|
+
];
|
|
246
|
+
|
|
247
|
+
try {
|
|
248
|
+
// Try to parse as URL
|
|
249
|
+
const url = new URL(normalizedPath.startsWith("//") ? "http:" + normalizedPath : normalizedPath);
|
|
250
|
+
|
|
251
|
+
const hostname = url.hostname.toLowerCase();
|
|
252
|
+
|
|
253
|
+
// Check against local patterns
|
|
254
|
+
for (const pattern of localPatterns) {
|
|
255
|
+
if (hostname === pattern || hostname.startsWith(pattern) || hostname.endsWith(pattern)) {
|
|
256
|
+
return true;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Check for IP addresses in private ranges
|
|
261
|
+
if (isPrivateIP(hostname)) {
|
|
262
|
+
return true;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Check for non-standard ports that might indicate internal services
|
|
266
|
+
const port = url.port;
|
|
267
|
+
if (port && isInternalPort(parseInt(port))) {
|
|
268
|
+
return true;
|
|
269
|
+
}
|
|
270
|
+
} catch (e) {
|
|
271
|
+
// If URL parsing fails, check if it's a relative path or contains suspicious patterns
|
|
272
|
+
|
|
273
|
+
// Relative paths starting with / are generally safe for same-origin
|
|
274
|
+
if (normalizedPath.startsWith("/") && !normalizedPath.startsWith("//")) {
|
|
275
|
+
return false;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Check for localhost patterns in non-URL strings
|
|
279
|
+
for (const pattern of localPatterns) {
|
|
280
|
+
if (normalizedPath.includes(pattern)) {
|
|
281
|
+
return true;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
return false;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Helper function to check if an IP address is in a private range
|
|
291
|
+
*/
|
|
292
|
+
function isPrivateIP(ip: string): boolean {
|
|
293
|
+
const ipRegex = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
|
|
294
|
+
const match = ip.match(ipRegex);
|
|
295
|
+
|
|
296
|
+
if (!match) {
|
|
297
|
+
return false;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
const [, a, b, c, d] = match.map(Number);
|
|
301
|
+
|
|
302
|
+
// Validate IP format
|
|
303
|
+
if (a > 255 || b > 255 || c > 255 || d > 255) {
|
|
304
|
+
return false;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Private IP ranges
|
|
308
|
+
return (
|
|
309
|
+
a === 10 || a === 127 || (a === 172 && b >= 16 && b <= 31) || (a === 192 && b === 168) || (a === 169 && b === 254) // Link-local
|
|
310
|
+
);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Helper function to check if a port is typically used for internal services
|
|
315
|
+
*/
|
|
316
|
+
function isInternalPort(port: number): boolean {
|
|
317
|
+
const internalPorts = [
|
|
318
|
+
22, // SSH
|
|
319
|
+
23, // Telnet
|
|
320
|
+
25, // SMTP
|
|
321
|
+
53, // DNS
|
|
322
|
+
135, // RPC
|
|
323
|
+
139, // NetBIOS
|
|
324
|
+
445, // SMB
|
|
325
|
+
993, // IMAPS
|
|
326
|
+
995, // POP3S
|
|
327
|
+
1433, // SQL Server
|
|
328
|
+
1521, // Oracle
|
|
329
|
+
3306, // MySQL
|
|
330
|
+
3389, // RDP
|
|
331
|
+
5432, // PostgreSQL
|
|
332
|
+
5900, // VNC
|
|
333
|
+
6379, // Redis
|
|
334
|
+
8080, // Common internal web
|
|
335
|
+
8443, // Common internal HTTPS
|
|
336
|
+
9200, // Elasticsearch
|
|
337
|
+
27017, // MongoDB
|
|
338
|
+
];
|
|
339
|
+
|
|
340
|
+
return internalPorts.includes(port);
|
|
341
|
+
}
|
|
171
342
|
/**
|
|
172
343
|
* Determines whether the given path is a filesystem path.
|
|
173
344
|
* This includes "file://" URLs.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@apidevtools/json-schema-ref-parser",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "14.0.0",
|
|
4
4
|
"description": "Parse, Resolve, and Dereference JSON Schema $ref pointers",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"prepublishOnly": "yarn build",
|
|
@@ -67,16 +67,16 @@
|
|
|
67
67
|
"cjs"
|
|
68
68
|
],
|
|
69
69
|
"devDependencies": {
|
|
70
|
-
"@eslint/compat": "^1.
|
|
71
|
-
"@eslint/js": "^9.
|
|
70
|
+
"@eslint/compat": "^1.3.0",
|
|
71
|
+
"@eslint/js": "^9.29.0",
|
|
72
72
|
"@types/eslint": "^9.6.1",
|
|
73
73
|
"@types/js-yaml": "^4.0.9",
|
|
74
74
|
"@types/node": "^24",
|
|
75
|
-
"@typescript-eslint/eslint-plugin": "^8.34.
|
|
76
|
-
"@typescript-eslint/parser": "^8.34.
|
|
75
|
+
"@typescript-eslint/eslint-plugin": "^8.34.1",
|
|
76
|
+
"@typescript-eslint/parser": "^8.34.1",
|
|
77
77
|
"@vitest/coverage-v8": "^3.2.3",
|
|
78
78
|
"cross-env": "^7.0.3",
|
|
79
|
-
"eslint": "^9.
|
|
79
|
+
"eslint": "^9.29.0",
|
|
80
80
|
"eslint-config-prettier": "^10.1.5",
|
|
81
81
|
"eslint-config-standard": "^17.1.0",
|
|
82
82
|
"eslint-plugin-import": "^2.31.0",
|
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
"prettier": "^3.5.3",
|
|
89
89
|
"rimraf": "^6.0.1",
|
|
90
90
|
"typescript": "^5.8.3",
|
|
91
|
-
"typescript-eslint": "^8.34.
|
|
91
|
+
"typescript-eslint": "^8.34.1",
|
|
92
92
|
"vitest": "^3.2.3"
|
|
93
93
|
},
|
|
94
94
|
"dependencies": {
|