@ai-sdk/provider-utils 4.0.17 → 4.0.19
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/CHANGELOG.md +12 -0
- package/dist/index.d.mts +10 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.js +103 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +102 -4
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/download-blob.ts +2 -0
- package/src/index.ts +1 -0
- package/src/secure-json-parse.ts +6 -2
- package/src/validate-download-url.ts +143 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @ai-sdk/provider-utils
|
|
2
2
|
|
|
3
|
+
## 4.0.19
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- ad4cfc2: Add URL validation to `downloadBlob` and `download` to prevent blind SSRF attacks. Private/internal IP addresses, localhost, and non-HTTP protocols are now rejected before fetching.
|
|
8
|
+
|
|
9
|
+
## 4.0.18
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 824b295: fix(provider-utils): prevent unicode escape bypass in secureJsonParse
|
|
14
|
+
|
|
3
15
|
## 4.0.17
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/dist/index.d.mts
CHANGED
|
@@ -1290,6 +1290,15 @@ declare function convertBase64ToUint8Array(base64String: string): Uint8Array<Arr
|
|
|
1290
1290
|
declare function convertUint8ArrayToBase64(array: Uint8Array): string;
|
|
1291
1291
|
declare function convertToBase64(value: string | Uint8Array): string;
|
|
1292
1292
|
|
|
1293
|
+
/**
|
|
1294
|
+
* Validates that a URL is safe to download from, blocking private/internal addresses
|
|
1295
|
+
* to prevent SSRF attacks.
|
|
1296
|
+
*
|
|
1297
|
+
* @param url - The URL string to validate.
|
|
1298
|
+
* @throws DownloadError if the URL is unsafe.
|
|
1299
|
+
*/
|
|
1300
|
+
declare function validateDownloadUrl(url: string): void;
|
|
1301
|
+
|
|
1293
1302
|
/**
|
|
1294
1303
|
* Validates the types of an unknown object using a schema and
|
|
1295
1304
|
* return a strongly-typed object.
|
|
@@ -1421,4 +1430,4 @@ interface ToolResult<NAME extends string, INPUT, OUTPUT> {
|
|
|
1421
1430
|
*/
|
|
1422
1431
|
type ToolCallOptions = ToolExecutionOptions;
|
|
1423
1432
|
|
|
1424
|
-
export { type AssistantContent, type AssistantModelMessage, DEFAULT_MAX_DOWNLOAD_SIZE, type DataContent, DelayedPromise, DownloadError, type FetchFunction, type FilePart, type FlexibleSchema, type IdGenerator, type ImagePart, type InferSchema, type InferToolInput, type InferToolOutput, type LazySchema, type MaybePromiseLike, type ModelMessage, type ParseResult, type ProviderOptions, type ProviderToolFactory, type ProviderToolFactoryWithOutputSchema, type ReasoningPart, type Resolvable, type ResponseHandler, type Schema, type SystemModelMessage, type TextPart, type Tool, type ToolApprovalRequest, type ToolApprovalResponse, type ToolCall, type ToolCallOptions, type ToolCallPart, type ToolContent, type ToolExecuteFunction, type ToolExecutionOptions, type ToolModelMessage, type ToolNameMapping, type ToolNeedsApprovalFunction, type ToolResult, type ToolResultOutput, type ToolResultPart, type UserContent, type UserModelMessage, VERSION, type ValidationResult, asSchema, combineHeaders, convertAsyncIteratorToReadableStream, convertBase64ToUint8Array, convertImageModelFileToDataUri, convertToBase64, convertToFormData, convertUint8ArrayToBase64, createBinaryResponseHandler, createEventSourceResponseHandler, createIdGenerator, createJsonErrorResponseHandler, createJsonResponseHandler, createProviderToolFactory, createProviderToolFactoryWithOutputSchema, createStatusCodeErrorResponseHandler, createToolNameMapping, delay, downloadBlob, dynamicTool, executeTool, extractResponseHeaders, generateId, getErrorMessage, getFromApi, getRuntimeEnvironmentUserAgent, injectJsonInstructionIntoMessages, isAbortError, isNonNullable, isParsableJson, isUrlSupported, jsonSchema, lazySchema, loadApiKey, loadOptionalSetting, loadSetting, mediaTypeToExtension, normalizeHeaders, parseJSON, parseJsonEventStream, parseProviderOptions, postFormDataToApi, postJsonToApi, postToApi, readResponseWithSizeLimit, removeUndefinedEntries, resolve, safeParseJSON, safeValidateTypes, stripFileExtension, tool, validateTypes, withUserAgentSuffix, withoutTrailingSlash, zodSchema };
|
|
1433
|
+
export { type AssistantContent, type AssistantModelMessage, DEFAULT_MAX_DOWNLOAD_SIZE, type DataContent, DelayedPromise, DownloadError, type FetchFunction, type FilePart, type FlexibleSchema, type IdGenerator, type ImagePart, type InferSchema, type InferToolInput, type InferToolOutput, type LazySchema, type MaybePromiseLike, type ModelMessage, type ParseResult, type ProviderOptions, type ProviderToolFactory, type ProviderToolFactoryWithOutputSchema, type ReasoningPart, type Resolvable, type ResponseHandler, type Schema, type SystemModelMessage, type TextPart, type Tool, type ToolApprovalRequest, type ToolApprovalResponse, type ToolCall, type ToolCallOptions, type ToolCallPart, type ToolContent, type ToolExecuteFunction, type ToolExecutionOptions, type ToolModelMessage, type ToolNameMapping, type ToolNeedsApprovalFunction, type ToolResult, type ToolResultOutput, type ToolResultPart, type UserContent, type UserModelMessage, VERSION, type ValidationResult, asSchema, combineHeaders, convertAsyncIteratorToReadableStream, convertBase64ToUint8Array, convertImageModelFileToDataUri, convertToBase64, convertToFormData, convertUint8ArrayToBase64, createBinaryResponseHandler, createEventSourceResponseHandler, createIdGenerator, createJsonErrorResponseHandler, createJsonResponseHandler, createProviderToolFactory, createProviderToolFactoryWithOutputSchema, createStatusCodeErrorResponseHandler, createToolNameMapping, delay, downloadBlob, dynamicTool, executeTool, extractResponseHeaders, generateId, getErrorMessage, getFromApi, getRuntimeEnvironmentUserAgent, injectJsonInstructionIntoMessages, isAbortError, isNonNullable, isParsableJson, isUrlSupported, jsonSchema, lazySchema, loadApiKey, loadOptionalSetting, loadSetting, mediaTypeToExtension, normalizeHeaders, parseJSON, parseJsonEventStream, parseProviderOptions, postFormDataToApi, postJsonToApi, postToApi, readResponseWithSizeLimit, removeUndefinedEntries, resolve, safeParseJSON, safeValidateTypes, stripFileExtension, tool, validateDownloadUrl, validateTypes, withUserAgentSuffix, withoutTrailingSlash, zodSchema };
|
package/dist/index.d.ts
CHANGED
|
@@ -1290,6 +1290,15 @@ declare function convertBase64ToUint8Array(base64String: string): Uint8Array<Arr
|
|
|
1290
1290
|
declare function convertUint8ArrayToBase64(array: Uint8Array): string;
|
|
1291
1291
|
declare function convertToBase64(value: string | Uint8Array): string;
|
|
1292
1292
|
|
|
1293
|
+
/**
|
|
1294
|
+
* Validates that a URL is safe to download from, blocking private/internal addresses
|
|
1295
|
+
* to prevent SSRF attacks.
|
|
1296
|
+
*
|
|
1297
|
+
* @param url - The URL string to validate.
|
|
1298
|
+
* @throws DownloadError if the URL is unsafe.
|
|
1299
|
+
*/
|
|
1300
|
+
declare function validateDownloadUrl(url: string): void;
|
|
1301
|
+
|
|
1293
1302
|
/**
|
|
1294
1303
|
* Validates the types of an unknown object using a schema and
|
|
1295
1304
|
* return a strongly-typed object.
|
|
@@ -1421,4 +1430,4 @@ interface ToolResult<NAME extends string, INPUT, OUTPUT> {
|
|
|
1421
1430
|
*/
|
|
1422
1431
|
type ToolCallOptions = ToolExecutionOptions;
|
|
1423
1432
|
|
|
1424
|
-
export { type AssistantContent, type AssistantModelMessage, DEFAULT_MAX_DOWNLOAD_SIZE, type DataContent, DelayedPromise, DownloadError, type FetchFunction, type FilePart, type FlexibleSchema, type IdGenerator, type ImagePart, type InferSchema, type InferToolInput, type InferToolOutput, type LazySchema, type MaybePromiseLike, type ModelMessage, type ParseResult, type ProviderOptions, type ProviderToolFactory, type ProviderToolFactoryWithOutputSchema, type ReasoningPart, type Resolvable, type ResponseHandler, type Schema, type SystemModelMessage, type TextPart, type Tool, type ToolApprovalRequest, type ToolApprovalResponse, type ToolCall, type ToolCallOptions, type ToolCallPart, type ToolContent, type ToolExecuteFunction, type ToolExecutionOptions, type ToolModelMessage, type ToolNameMapping, type ToolNeedsApprovalFunction, type ToolResult, type ToolResultOutput, type ToolResultPart, type UserContent, type UserModelMessage, VERSION, type ValidationResult, asSchema, combineHeaders, convertAsyncIteratorToReadableStream, convertBase64ToUint8Array, convertImageModelFileToDataUri, convertToBase64, convertToFormData, convertUint8ArrayToBase64, createBinaryResponseHandler, createEventSourceResponseHandler, createIdGenerator, createJsonErrorResponseHandler, createJsonResponseHandler, createProviderToolFactory, createProviderToolFactoryWithOutputSchema, createStatusCodeErrorResponseHandler, createToolNameMapping, delay, downloadBlob, dynamicTool, executeTool, extractResponseHeaders, generateId, getErrorMessage, getFromApi, getRuntimeEnvironmentUserAgent, injectJsonInstructionIntoMessages, isAbortError, isNonNullable, isParsableJson, isUrlSupported, jsonSchema, lazySchema, loadApiKey, loadOptionalSetting, loadSetting, mediaTypeToExtension, normalizeHeaders, parseJSON, parseJsonEventStream, parseProviderOptions, postFormDataToApi, postJsonToApi, postToApi, readResponseWithSizeLimit, removeUndefinedEntries, resolve, safeParseJSON, safeValidateTypes, stripFileExtension, tool, validateTypes, withUserAgentSuffix, withoutTrailingSlash, zodSchema };
|
|
1433
|
+
export { type AssistantContent, type AssistantModelMessage, DEFAULT_MAX_DOWNLOAD_SIZE, type DataContent, DelayedPromise, DownloadError, type FetchFunction, type FilePart, type FlexibleSchema, type IdGenerator, type ImagePart, type InferSchema, type InferToolInput, type InferToolOutput, type LazySchema, type MaybePromiseLike, type ModelMessage, type ParseResult, type ProviderOptions, type ProviderToolFactory, type ProviderToolFactoryWithOutputSchema, type ReasoningPart, type Resolvable, type ResponseHandler, type Schema, type SystemModelMessage, type TextPart, type Tool, type ToolApprovalRequest, type ToolApprovalResponse, type ToolCall, type ToolCallOptions, type ToolCallPart, type ToolContent, type ToolExecuteFunction, type ToolExecutionOptions, type ToolModelMessage, type ToolNameMapping, type ToolNeedsApprovalFunction, type ToolResult, type ToolResultOutput, type ToolResultPart, type UserContent, type UserModelMessage, VERSION, type ValidationResult, asSchema, combineHeaders, convertAsyncIteratorToReadableStream, convertBase64ToUint8Array, convertImageModelFileToDataUri, convertToBase64, convertToFormData, convertUint8ArrayToBase64, createBinaryResponseHandler, createEventSourceResponseHandler, createIdGenerator, createJsonErrorResponseHandler, createJsonResponseHandler, createProviderToolFactory, createProviderToolFactoryWithOutputSchema, createStatusCodeErrorResponseHandler, createToolNameMapping, delay, downloadBlob, dynamicTool, executeTool, extractResponseHeaders, generateId, getErrorMessage, getFromApi, getRuntimeEnvironmentUserAgent, injectJsonInstructionIntoMessages, isAbortError, isNonNullable, isParsableJson, isUrlSupported, jsonSchema, lazySchema, loadApiKey, loadOptionalSetting, loadSetting, mediaTypeToExtension, normalizeHeaders, parseJSON, parseJsonEventStream, parseProviderOptions, postFormDataToApi, postJsonToApi, postToApi, readResponseWithSizeLimit, removeUndefinedEntries, resolve, safeParseJSON, safeValidateTypes, stripFileExtension, tool, validateDownloadUrl, validateTypes, withUserAgentSuffix, withoutTrailingSlash, zodSchema };
|
package/dist/index.js
CHANGED
|
@@ -86,6 +86,7 @@ __export(src_exports, {
|
|
|
86
86
|
safeValidateTypes: () => safeValidateTypes,
|
|
87
87
|
stripFileExtension: () => stripFileExtension,
|
|
88
88
|
tool: () => tool,
|
|
89
|
+
validateDownloadUrl: () => validateDownloadUrl,
|
|
89
90
|
validateTypes: () => validateTypes,
|
|
90
91
|
withUserAgentSuffix: () => withUserAgentSuffix,
|
|
91
92
|
withoutTrailingSlash: () => withoutTrailingSlash,
|
|
@@ -383,9 +384,106 @@ async function readResponseWithSizeLimit({
|
|
|
383
384
|
return result;
|
|
384
385
|
}
|
|
385
386
|
|
|
387
|
+
// src/validate-download-url.ts
|
|
388
|
+
function validateDownloadUrl(url) {
|
|
389
|
+
let parsed;
|
|
390
|
+
try {
|
|
391
|
+
parsed = new URL(url);
|
|
392
|
+
} catch (e) {
|
|
393
|
+
throw new DownloadError({
|
|
394
|
+
url,
|
|
395
|
+
message: `Invalid URL: ${url}`
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
399
|
+
throw new DownloadError({
|
|
400
|
+
url,
|
|
401
|
+
message: `URL scheme must be http or https, got ${parsed.protocol}`
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
const hostname = parsed.hostname;
|
|
405
|
+
if (!hostname) {
|
|
406
|
+
throw new DownloadError({
|
|
407
|
+
url,
|
|
408
|
+
message: `URL must have a hostname`
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
if (hostname === "localhost" || hostname.endsWith(".local") || hostname.endsWith(".localhost")) {
|
|
412
|
+
throw new DownloadError({
|
|
413
|
+
url,
|
|
414
|
+
message: `URL with hostname ${hostname} is not allowed`
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
if (hostname.startsWith("[") && hostname.endsWith("]")) {
|
|
418
|
+
const ipv6 = hostname.slice(1, -1);
|
|
419
|
+
if (isPrivateIPv6(ipv6)) {
|
|
420
|
+
throw new DownloadError({
|
|
421
|
+
url,
|
|
422
|
+
message: `URL with IPv6 address ${hostname} is not allowed`
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
if (isIPv4(hostname)) {
|
|
428
|
+
if (isPrivateIPv4(hostname)) {
|
|
429
|
+
throw new DownloadError({
|
|
430
|
+
url,
|
|
431
|
+
message: `URL with IP address ${hostname} is not allowed`
|
|
432
|
+
});
|
|
433
|
+
}
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
function isIPv4(hostname) {
|
|
438
|
+
const parts = hostname.split(".");
|
|
439
|
+
if (parts.length !== 4) return false;
|
|
440
|
+
return parts.every((part) => {
|
|
441
|
+
const num = Number(part);
|
|
442
|
+
return Number.isInteger(num) && num >= 0 && num <= 255 && String(num) === part;
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
function isPrivateIPv4(ip) {
|
|
446
|
+
const parts = ip.split(".").map(Number);
|
|
447
|
+
const [a, b] = parts;
|
|
448
|
+
if (a === 0) return true;
|
|
449
|
+
if (a === 10) return true;
|
|
450
|
+
if (a === 127) return true;
|
|
451
|
+
if (a === 169 && b === 254) return true;
|
|
452
|
+
if (a === 172 && b >= 16 && b <= 31) return true;
|
|
453
|
+
if (a === 192 && b === 168) return true;
|
|
454
|
+
return false;
|
|
455
|
+
}
|
|
456
|
+
function isPrivateIPv6(ip) {
|
|
457
|
+
const normalized = ip.toLowerCase();
|
|
458
|
+
if (normalized === "::1") return true;
|
|
459
|
+
if (normalized === "::") return true;
|
|
460
|
+
if (normalized.startsWith("::ffff:")) {
|
|
461
|
+
const mappedPart = normalized.slice(7);
|
|
462
|
+
if (isIPv4(mappedPart)) {
|
|
463
|
+
return isPrivateIPv4(mappedPart);
|
|
464
|
+
}
|
|
465
|
+
const hexParts = mappedPart.split(":");
|
|
466
|
+
if (hexParts.length === 2) {
|
|
467
|
+
const high = parseInt(hexParts[0], 16);
|
|
468
|
+
const low = parseInt(hexParts[1], 16);
|
|
469
|
+
if (!isNaN(high) && !isNaN(low)) {
|
|
470
|
+
const a = high >> 8 & 255;
|
|
471
|
+
const b = high & 255;
|
|
472
|
+
const c = low >> 8 & 255;
|
|
473
|
+
const d = low & 255;
|
|
474
|
+
return isPrivateIPv4(`${a}.${b}.${c}.${d}`);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
if (normalized.startsWith("fc") || normalized.startsWith("fd")) return true;
|
|
479
|
+
if (normalized.startsWith("fe80")) return true;
|
|
480
|
+
return false;
|
|
481
|
+
}
|
|
482
|
+
|
|
386
483
|
// src/download-blob.ts
|
|
387
484
|
async function downloadBlob(url, options) {
|
|
388
485
|
var _a2, _b2;
|
|
486
|
+
validateDownloadUrl(url);
|
|
389
487
|
try {
|
|
390
488
|
const response = await fetch(url, {
|
|
391
489
|
signal: options == null ? void 0 : options.abortSignal
|
|
@@ -574,7 +672,7 @@ function withUserAgentSuffix(headers, ...userAgentSuffixParts) {
|
|
|
574
672
|
}
|
|
575
673
|
|
|
576
674
|
// src/version.ts
|
|
577
|
-
var VERSION = true ? "4.0.
|
|
675
|
+
var VERSION = true ? "4.0.19" : "0.0.0-test";
|
|
578
676
|
|
|
579
677
|
// src/get-from-api.ts
|
|
580
678
|
var getOriginalFetch = () => globalThis.fetch;
|
|
@@ -809,8 +907,8 @@ function mediaTypeToExtension(mediaType) {
|
|
|
809
907
|
var import_provider9 = require("@ai-sdk/provider");
|
|
810
908
|
|
|
811
909
|
// src/secure-json-parse.ts
|
|
812
|
-
var suspectProtoRx = /"
|
|
813
|
-
var suspectConstructorRx = /"
|
|
910
|
+
var suspectProtoRx = /"(?:_|\\u005[Ff])(?:_|\\u005[Ff])(?:p|\\u0070)(?:r|\\u0072)(?:o|\\u006[Ff])(?:t|\\u0074)(?:o|\\u006[Ff])(?:_|\\u005[Ff])(?:_|\\u005[Ff])"\s*:/;
|
|
911
|
+
var suspectConstructorRx = /"(?:c|\\u0063)(?:o|\\u006[Ff])(?:n|\\u006[Ee])(?:s|\\u0073)(?:t|\\u0074)(?:r|\\u0072)(?:u|\\u0075)(?:c|\\u0063)(?:t|\\u0074)(?:o|\\u006[Ff])(?:r|\\u0072)"\s*:/;
|
|
814
912
|
function _parse(text) {
|
|
815
913
|
const obj = JSON.parse(text);
|
|
816
914
|
if (obj === null || typeof obj !== "object") {
|
|
@@ -830,7 +928,7 @@ function filter(obj) {
|
|
|
830
928
|
if (Object.prototype.hasOwnProperty.call(node, "__proto__")) {
|
|
831
929
|
throw new SyntaxError("Object contains forbidden prototype property");
|
|
832
930
|
}
|
|
833
|
-
if (Object.prototype.hasOwnProperty.call(node, "constructor") && Object.prototype.hasOwnProperty.call(node.constructor, "prototype")) {
|
|
931
|
+
if (Object.prototype.hasOwnProperty.call(node, "constructor") && node.constructor !== null && typeof node.constructor === "object" && Object.prototype.hasOwnProperty.call(node.constructor, "prototype")) {
|
|
834
932
|
throw new SyntaxError("Object contains forbidden prototype property");
|
|
835
933
|
}
|
|
836
934
|
for (const key in node) {
|
|
@@ -2737,6 +2835,7 @@ var import_stream2 = require("eventsource-parser/stream");
|
|
|
2737
2835
|
safeValidateTypes,
|
|
2738
2836
|
stripFileExtension,
|
|
2739
2837
|
tool,
|
|
2838
|
+
validateDownloadUrl,
|
|
2740
2839
|
validateTypes,
|
|
2741
2840
|
withUserAgentSuffix,
|
|
2742
2841
|
withoutTrailingSlash,
|