@apidevtools/json-schema-ref-parser 13.0.4 → 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.
@@ -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,
@@ -55,7 +56,7 @@ export declare class $RefParser<S extends object = JSONSchema, O extends ParserO
55
56
  *
56
57
  * Resolves all JSON references (`$ref` pointers) in the given JSON Schema file. If it references any other files/URLs, then they will be downloaded and resolved as well. This method **does not** dereference anything. It simply gives you a `$Refs` object, which is a map of all the resolved references and their values.
57
58
  *
58
- * See https://apitools.dev/json-schema-ref-parser/docs/ref-parser.html#resolveschema-options-callback
59
+ * See https://apidevtools.com/json-schema-ref-parser/docs/ref-parser.html#resolveschema-options-callback
59
60
  *
60
61
  * @param schema A JSON Schema object, or the file path or URL of a JSON Schema file. See the `parse` method for more info.
61
62
  * @param options (optional)
@@ -72,7 +73,7 @@ export declare class $RefParser<S extends object = JSONSchema, O extends ParserO
72
73
  *
73
74
  * Resolves all JSON references (`$ref` pointers) in the given JSON Schema file. If it references any other files/URLs, then they will be downloaded and resolved as well. This method **does not** dereference anything. It simply gives you a `$Refs` object, which is a map of all the resolved references and their values.
74
75
  *
75
- * See https://apitools.dev/json-schema-ref-parser/docs/ref-parser.html#resolveschema-options-callback
76
+ * See https://apidevtools.com/json-schema-ref-parser/docs/ref-parser.html#resolveschema-options-callback
76
77
  *
77
78
  * @param schema A JSON Schema object, or the file path or URL of a JSON Schema file. See the `parse` method for more info.
78
79
  * @param options (optional)
@@ -89,7 +90,7 @@ export declare class $RefParser<S extends object = JSONSchema, O extends ParserO
89
90
  *
90
91
  * This also eliminates the risk of circular references, so the schema can be safely serialized using `JSON.stringify()`.
91
92
  *
92
- * See https://apitools.dev/json-schema-ref-parser/docs/ref-parser.html#bundleschema-options-callback
93
+ * See https://apidevtools.com/json-schema-ref-parser/docs/ref-parser.html#bundleschema-options-callback
93
94
  *
94
95
  * @param schema A JSON Schema object, or the file path or URL of a JSON Schema file. See the `parse` method for more info.
95
96
  * @param options (optional)
@@ -106,7 +107,7 @@ export declare class $RefParser<S extends object = JSONSchema, O extends ParserO
106
107
  *
107
108
  * This also eliminates the risk of circular references, so the schema can be safely serialized using `JSON.stringify()`.
108
109
  *
109
- * See https://apitools.dev/json-schema-ref-parser/docs/ref-parser.html#bundleschema-options-callback
110
+ * See https://apidevtools.com/json-schema-ref-parser/docs/ref-parser.html#bundleschema-options-callback
110
111
  *
111
112
  * @param schema A JSON Schema object, or the file path or URL of a JSON Schema file. See the `parse` method for more info.
112
113
  * @param options (optional)
@@ -123,7 +124,7 @@ export declare class $RefParser<S extends object = JSONSchema, O extends ParserO
123
124
  *
124
125
  * The dereference method maintains object reference equality, meaning that all `$ref` pointers that point to the same object will be replaced with references to the same object. Again, this is great for programmatic usage, but it does introduce the risk of circular references, so be careful if you intend to serialize the schema using `JSON.stringify()`. Consider using the bundle method instead, which does not create circular references.
125
126
  *
126
- * See https://apitools.dev/json-schema-ref-parser/docs/ref-parser.html#dereferenceschema-options-callback
127
+ * See https://apidevtools.com/json-schema-ref-parser/docs/ref-parser.html#dereferenceschema-options-callback
127
128
  *
128
129
  * @param schema A JSON Schema object, or the file path or URL of a JSON Schema file. See the `parse` method for more info.
129
130
  * @param options (optional)
@@ -140,7 +141,7 @@ export declare class $RefParser<S extends object = JSONSchema, O extends ParserO
140
141
  *
141
142
  * The dereference method maintains object reference equality, meaning that all `$ref` pointers that point to the same object will be replaced with references to the same object. Again, this is great for programmatic usage, but it does introduce the risk of circular references, so be careful if you intend to serialize the schema using `JSON.stringify()`. Consider using the bundle method instead, which does not create circular references.
142
143
  *
143
- * See https://apitools.dev/json-schema-ref-parser/docs/ref-parser.html#dereferenceschema-options-callback
144
+ * See https://apidevtools.com/json-schema-ref-parser/docs/ref-parser.html#dereferenceschema-options-callback
144
145
  *
145
146
  * @param path
146
147
  * @param schema A JSON Schema object, or the file path or URL of a JSON Schema file. See the `parse` method for more info.
@@ -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.
@@ -10,19 +10,19 @@ interface $RefsMap<S extends object = JSONSchema, O extends ParserOptions<S> = P
10
10
  *
11
11
  * This object is a map of JSON References and their resolved values. It also has several convenient helper methods that make it easy for you to navigate and manipulate the JSON References.
12
12
  *
13
- * See https://apitools.dev/json-schema-ref-parser/docs/refs.html
13
+ * See https://apidevtools.com/json-schema-ref-parser/docs/refs.html
14
14
  */
15
15
  export default class $Refs<S extends object = JSONSchema, O extends ParserOptions<S> = ParserOptions<S>> {
16
16
  /**
17
17
  * This property is true if the schema contains any circular references. You may want to check this property before serializing the dereferenced schema as JSON, since JSON.stringify() does not support circular references by default.
18
18
  *
19
- * See https://apitools.dev/json-schema-ref-parser/docs/refs.html#circular
19
+ * See https://apidevtools.com/json-schema-ref-parser/docs/refs.html#circular
20
20
  */
21
21
  circular: boolean;
22
22
  /**
23
23
  * Returns the paths/URLs of all the files in your schema (including the main schema file).
24
24
  *
25
- * See https://apitools.dev/json-schema-ref-parser/docs/refs.html#pathstypes
25
+ * See https://apidevtools.com/json-schema-ref-parser/docs/refs.html#pathstypes
26
26
  *
27
27
  * @param types (optional) Optionally only return certain types of paths ("file", "http", etc.)
28
28
  */
@@ -30,7 +30,7 @@ export default class $Refs<S extends object = JSONSchema, O extends ParserOption
30
30
  /**
31
31
  * Returns a map of paths/URLs and their correspond values.
32
32
  *
33
- * See https://apitools.dev/json-schema-ref-parser/docs/refs.html#valuestypes
33
+ * See https://apidevtools.com/json-schema-ref-parser/docs/refs.html#valuestypes
34
34
  *
35
35
  * @param types (optional) Optionally only return values from certain locations ("file", "http", etc.)
36
36
  */
@@ -38,7 +38,7 @@ export default class $Refs<S extends object = JSONSchema, O extends ParserOption
38
38
  /**
39
39
  * Returns `true` if the given path exists in the schema; otherwise, returns `false`
40
40
  *
41
- * See https://apitools.dev/json-schema-ref-parser/docs/refs.html#existsref
41
+ * See https://apidevtools.com/json-schema-ref-parser/docs/refs.html#existsref
42
42
  *
43
43
  * @param $ref The JSON Reference path, optionally with a JSON Pointer in the hash
44
44
  */
package/dist/lib/refs.js CHANGED
@@ -44,13 +44,13 @@ const convert_path_to_posix_1 = __importDefault(require("./util/convert-path-to-
44
44
  *
45
45
  * This object is a map of JSON References and their resolved values. It also has several convenient helper methods that make it easy for you to navigate and manipulate the JSON References.
46
46
  *
47
- * See https://apitools.dev/json-schema-ref-parser/docs/refs.html
47
+ * See https://apidevtools.com/json-schema-ref-parser/docs/refs.html
48
48
  */
49
49
  class $Refs {
50
50
  /**
51
51
  * Returns the paths/URLs of all the files in your schema (including the main schema file).
52
52
  *
53
- * See https://apitools.dev/json-schema-ref-parser/docs/refs.html#pathstypes
53
+ * See https://apidevtools.com/json-schema-ref-parser/docs/refs.html#pathstypes
54
54
  *
55
55
  * @param types (optional) Optionally only return certain types of paths ("file", "http", etc.)
56
56
  */
@@ -63,7 +63,7 @@ class $Refs {
63
63
  /**
64
64
  * Returns a map of paths/URLs and their correspond values.
65
65
  *
66
- * See https://apitools.dev/json-schema-ref-parser/docs/refs.html#valuestypes
66
+ * See https://apidevtools.com/json-schema-ref-parser/docs/refs.html#valuestypes
67
67
  *
68
68
  * @param types (optional) Optionally only return values from certain locations ("file", "http", etc.)
69
69
  */
@@ -78,7 +78,7 @@ class $Refs {
78
78
  /**
79
79
  * Returns `true` if the given path exists in the schema; otherwise, returns `false`
80
80
  *
81
- * See https://apitools.dev/json-schema-ref-parser/docs/refs.html#existsref
81
+ * See https://apidevtools.com/json-schema-ref-parser/docs/refs.html#existsref
82
82
  *
83
83
  * @param $ref The JSON Reference path, optionally with a JSON Pointer in the hash
84
84
  */
@@ -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.
@@ -6,7 +6,7 @@ export type JSONSchemaObject = JSONSchema4Object | JSONSchema6Object | JSONSchem
6
6
  export type SchemaCallback<S extends object = JSONSchema> = (err: Error | null, schema?: S | object | null) => any;
7
7
  export type $RefsCallback<S extends object = JSONSchema, O extends ParserOptions<S> = ParserOptions<S>> = (err: Error | null, $refs?: $Refs<S, O>) => any;
8
8
  /**
9
- * See https://apitools.dev/json-schema-ref-parser/docs/options.html
9
+ * See https://apidevtools.com/json-schema-ref-parser/docs/options.html
10
10
  */
11
11
  export interface HTTPResolverOptions<S extends object = JSONSchema> extends Partial<ResolverOptions<S>> {
12
12
  /**
@@ -25,11 +25,15 @@ 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.
31
35
  *
32
- * See https://apitools.dev/json-schema-ref-parser/docs/plugins/resolvers.html
36
+ * See https://apidevtools.com/json-schema-ref-parser/docs/plugins/resolvers.html
33
37
  */
34
38
  export interface ResolverOptions<S extends object = JSONSchema> {
35
39
  name?: string;
@@ -92,7 +96,7 @@ export interface Plugin {
92
96
  *
93
97
  * The file info object currently only consists of a few properties, but it may grow in the future if plug-ins end up needing more information.
94
98
  *
95
- * See https://apitools.dev/json-schema-ref-parser/docs/plugins/file-info-object.html
99
+ * See https://apidevtools.com/json-schema-ref-parser/docs/plugins/file-info-object.html
96
100
  */
97
101
  export interface FileInfo {
98
102
  /**
@@ -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.
@@ -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
 
@@ -180,7 +181,7 @@ export class $RefParser<S extends object = JSONSchema, O extends ParserOptions<S
180
181
  *
181
182
  * Resolves all JSON references (`$ref` pointers) in the given JSON Schema file. If it references any other files/URLs, then they will be downloaded and resolved as well. This method **does not** dereference anything. It simply gives you a `$Refs` object, which is a map of all the resolved references and their values.
182
183
  *
183
- * See https://apitools.dev/json-schema-ref-parser/docs/ref-parser.html#resolveschema-options-callback
184
+ * See https://apidevtools.com/json-schema-ref-parser/docs/ref-parser.html#resolveschema-options-callback
184
185
  *
185
186
  * @param schema A JSON Schema object, or the file path or URL of a JSON Schema file. See the `parse` method for more info.
186
187
  * @param options (optional)
@@ -210,7 +211,7 @@ export class $RefParser<S extends object = JSONSchema, O extends ParserOptions<S
210
211
  *
211
212
  * Resolves all JSON references (`$ref` pointers) in the given JSON Schema file. If it references any other files/URLs, then they will be downloaded and resolved as well. This method **does not** dereference anything. It simply gives you a `$Refs` object, which is a map of all the resolved references and their values.
212
213
  *
213
- * See https://apitools.dev/json-schema-ref-parser/docs/ref-parser.html#resolveschema-options-callback
214
+ * See https://apidevtools.com/json-schema-ref-parser/docs/ref-parser.html#resolveschema-options-callback
214
215
  *
215
216
  * @param schema A JSON Schema object, or the file path or URL of a JSON Schema file. See the `parse` method for more info.
216
217
  * @param options (optional)
@@ -255,7 +256,7 @@ export class $RefParser<S extends object = JSONSchema, O extends ParserOptions<S
255
256
  *
256
257
  * This also eliminates the risk of circular references, so the schema can be safely serialized using `JSON.stringify()`.
257
258
  *
258
- * See https://apitools.dev/json-schema-ref-parser/docs/ref-parser.html#bundleschema-options-callback
259
+ * See https://apidevtools.com/json-schema-ref-parser/docs/ref-parser.html#bundleschema-options-callback
259
260
  *
260
261
  * @param schema A JSON Schema object, or the file path or URL of a JSON Schema file. See the `parse` method for more info.
261
262
  * @param options (optional)
@@ -298,7 +299,7 @@ export class $RefParser<S extends object = JSONSchema, O extends ParserOptions<S
298
299
  *
299
300
  * This also eliminates the risk of circular references, so the schema can be safely serialized using `JSON.stringify()`.
300
301
  *
301
- * See https://apitools.dev/json-schema-ref-parser/docs/ref-parser.html#bundleschema-options-callback
302
+ * See https://apidevtools.com/json-schema-ref-parser/docs/ref-parser.html#bundleschema-options-callback
302
303
  *
303
304
  * @param schema A JSON Schema object, or the file path or URL of a JSON Schema file. See the `parse` method for more info.
304
305
  * @param options (optional)
@@ -327,7 +328,7 @@ export class $RefParser<S extends object = JSONSchema, O extends ParserOptions<S
327
328
  *
328
329
  * The dereference method maintains object reference equality, meaning that all `$ref` pointers that point to the same object will be replaced with references to the same object. Again, this is great for programmatic usage, but it does introduce the risk of circular references, so be careful if you intend to serialize the schema using `JSON.stringify()`. Consider using the bundle method instead, which does not create circular references.
329
330
  *
330
- * See https://apitools.dev/json-schema-ref-parser/docs/ref-parser.html#dereferenceschema-options-callback
331
+ * See https://apidevtools.com/json-schema-ref-parser/docs/ref-parser.html#dereferenceschema-options-callback
331
332
  *
332
333
  * @param schema A JSON Schema object, or the file path or URL of a JSON Schema file. See the `parse` method for more info.
333
334
  * @param options (optional)
@@ -370,7 +371,7 @@ export class $RefParser<S extends object = JSONSchema, O extends ParserOptions<S
370
371
  *
371
372
  * The dereference method maintains object reference equality, meaning that all `$ref` pointers that point to the same object will be replaced with references to the same object. Again, this is great for programmatic usage, but it does introduce the risk of circular references, so be careful if you intend to serialize the schema using `JSON.stringify()`. Consider using the bundle method instead, which does not create circular references.
372
373
  *
373
- * See https://apitools.dev/json-schema-ref-parser/docs/ref-parser.html#dereferenceschema-options-callback
374
+ * See https://apidevtools.com/json-schema-ref-parser/docs/ref-parser.html#dereferenceschema-options-callback
374
375
  *
375
376
  * @param path
376
377
  * @param schema A JSON Schema object, or the file path or URL of a JSON Schema file. See the `parse` method for more info.
@@ -439,4 +440,5 @@ export {
439
440
  normalizeArgs as jsonSchemaParserNormalizeArgs,
440
441
  getJsonSchemaRefParserDefaultOptions,
441
442
  $Refs,
443
+ isUnsafeUrl,
442
444
  };
package/lib/refs.ts CHANGED
@@ -13,20 +13,20 @@ interface $RefsMap<S extends object = JSONSchema, O extends ParserOptions<S> = P
13
13
  *
14
14
  * This object is a map of JSON References and their resolved values. It also has several convenient helper methods that make it easy for you to navigate and manipulate the JSON References.
15
15
  *
16
- * See https://apitools.dev/json-schema-ref-parser/docs/refs.html
16
+ * See https://apidevtools.com/json-schema-ref-parser/docs/refs.html
17
17
  */
18
18
  export default class $Refs<S extends object = JSONSchema, O extends ParserOptions<S> = ParserOptions<S>> {
19
19
  /**
20
20
  * This property is true if the schema contains any circular references. You may want to check this property before serializing the dereferenced schema as JSON, since JSON.stringify() does not support circular references by default.
21
21
  *
22
- * See https://apitools.dev/json-schema-ref-parser/docs/refs.html#circular
22
+ * See https://apidevtools.com/json-schema-ref-parser/docs/refs.html#circular
23
23
  */
24
24
  public circular: boolean;
25
25
 
26
26
  /**
27
27
  * Returns the paths/URLs of all the files in your schema (including the main schema file).
28
28
  *
29
- * See https://apitools.dev/json-schema-ref-parser/docs/refs.html#pathstypes
29
+ * See https://apidevtools.com/json-schema-ref-parser/docs/refs.html#pathstypes
30
30
  *
31
31
  * @param types (optional) Optionally only return certain types of paths ("file", "http", etc.)
32
32
  */
@@ -40,7 +40,7 @@ export default class $Refs<S extends object = JSONSchema, O extends ParserOption
40
40
  /**
41
41
  * Returns a map of paths/URLs and their correspond values.
42
42
  *
43
- * See https://apitools.dev/json-schema-ref-parser/docs/refs.html#valuestypes
43
+ * See https://apidevtools.com/json-schema-ref-parser/docs/refs.html#valuestypes
44
44
  *
45
45
  * @param types (optional) Optionally only return values from certain locations ("file", "http", etc.)
46
46
  */
@@ -56,7 +56,7 @@ export default class $Refs<S extends object = JSONSchema, O extends ParserOption
56
56
  /**
57
57
  * Returns `true` if the given path exists in the schema; otherwise, returns `false`
58
58
  *
59
- * See https://apitools.dev/json-schema-ref-parser/docs/refs.html#existsref
59
+ * See https://apidevtools.com/json-schema-ref-parser/docs/refs.html#existsref
60
60
  *
61
61
  * @param $ref The JSON Reference path, optionally with a JSON Pointer in the hash
62
62
  */
@@ -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
  /**
@@ -18,7 +18,7 @@ export type $RefsCallback<S extends object = JSONSchema, O extends ParserOptions
18
18
  ) => any;
19
19
 
20
20
  /**
21
- * See https://apitools.dev/json-schema-ref-parser/docs/options.html
21
+ * See https://apidevtools.com/json-schema-ref-parser/docs/options.html
22
22
  */
23
23
 
24
24
  export interface HTTPResolverOptions<S extends object = JSONSchema> extends Partial<ResolverOptions<S>> {
@@ -41,12 +41,17 @@ 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
  /**
47
52
  * 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.
48
53
  *
49
- * See https://apitools.dev/json-schema-ref-parser/docs/plugins/resolvers.html
54
+ * See https://apidevtools.com/json-schema-ref-parser/docs/plugins/resolvers.html
50
55
  */
51
56
  export interface ResolverOptions<S extends object = JSONSchema> {
52
57
  name?: string;
@@ -126,7 +131,7 @@ export interface Plugin {
126
131
  *
127
132
  * The file info object currently only consists of a few properties, but it may grow in the future if plug-ins end up needing more information.
128
133
  *
129
- * See https://apitools.dev/json-schema-ref-parser/docs/plugins/file-info-object.html
134
+ * See https://apidevtools.com/json-schema-ref-parser/docs/plugins/file-info-object.html
130
135
  */
131
136
  export interface FileInfo {
132
137
  /**
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": "13.0.4",
3
+ "version": "14.0.0",
4
4
  "description": "Parse, Resolve, and Dereference JSON Schema $ref pointers",
5
5
  "scripts": {
6
6
  "prepublishOnly": "yarn build",
@@ -46,7 +46,7 @@
46
46
  "email": "apis@jonlu.ca"
47
47
  }
48
48
  ],
49
- "homepage": "https://apitools.dev/json-schema-ref-parser/",
49
+ "homepage": "https://apidevtools.com/json-schema-ref-parser/",
50
50
  "repository": {
51
51
  "type": "git",
52
52
  "url": "https://github.com/APIDevTools/json-schema-ref-parser.git"
@@ -67,16 +67,16 @@
67
67
  "cjs"
68
68
  ],
69
69
  "devDependencies": {
70
- "@eslint/compat": "^1.2.9",
71
- "@eslint/js": "^9.28.0",
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
- "@types/node": "^22",
75
- "@typescript-eslint/eslint-plugin": "^8.33.1",
76
- "@typescript-eslint/parser": "^8.33.1",
77
- "@vitest/coverage-v8": "^3.2.2",
74
+ "@types/node": "^24",
75
+ "@typescript-eslint/eslint-plugin": "^8.34.1",
76
+ "@typescript-eslint/parser": "^8.34.1",
77
+ "@vitest/coverage-v8": "^3.2.3",
78
78
  "cross-env": "^7.0.3",
79
- "eslint": "^9.28.0",
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,8 +88,8 @@
88
88
  "prettier": "^3.5.3",
89
89
  "rimraf": "^6.0.1",
90
90
  "typescript": "^5.8.3",
91
- "typescript-eslint": "^8.33.1",
92
- "vitest": "^3.2.2"
91
+ "typescript-eslint": "^8.34.1",
92
+ "vitest": "^3.2.3"
93
93
  },
94
94
  "dependencies": {
95
95
  "@types/json-schema": "^7.0.15",