@ai-sdk/google
Advanced tools
+15
-0
| # @ai-sdk/google | ||
| ## 3.0.82 | ||
| ### Patch Changes | ||
| - 3258f22: fix(google): prevent prototype pollution when streaming tool args | ||
| - bfa5864: fix: only send provider credentials to same-origin response-supplied URLs | ||
| Several provider clients followed a URL taken from the provider's API response (a polling/status URL or a final media URL such as `polling_url`, `urls.get`, `result_url`, `result.sample`, or `video.uri`) and reused the authenticated headers — or appended `?key=<API_KEY>` — on that request. Because the host of the response-supplied URL was never validated, the long-lived API key was sent to whatever host the response named (a CDN in the benign case, or an attacker-chosen host if the provider response was tampered with), allowing credential exfiltration. | ||
| A new `isSameOrigin` helper is added to `@ai-sdk/provider-utils`, and the affected fetches in `@ai-sdk/black-forest-labs`, `@ai-sdk/fireworks`, `@ai-sdk/replicate`, `@ai-sdk/gladia`, `@ai-sdk/fal`, and `@ai-sdk/google` now attach credentials only when the followed URL is same-origin with the provider's configured API origin. Requests to a foreign origin are made without the credential. | ||
| - Updated dependencies [bfa5864] | ||
| - Updated dependencies [f42aa79] | ||
| - @ai-sdk/provider-utils@4.0.29 | ||
| ## 3.0.81 | ||
@@ -4,0 +19,0 @@ |
+2
-2
| { | ||
| "name": "@ai-sdk/google", | ||
| "version": "3.0.81", | ||
| "version": "3.0.82", | ||
| "license": "Apache-2.0", | ||
@@ -39,3 +39,3 @@ "sideEffects": false, | ||
| "dependencies": { | ||
| "@ai-sdk/provider-utils": "4.0.28", | ||
| "@ai-sdk/provider-utils": "4.0.29", | ||
| "@ai-sdk/provider": "3.0.10" | ||
@@ -42,0 +42,0 @@ }, |
@@ -13,2 +13,3 @@ import { | ||
| getFromApi, | ||
| isSameOrigin, | ||
| lazySchema, | ||
@@ -283,6 +284,9 @@ parseProviderOptions, | ||
| if (generatedSample.video?.uri) { | ||
| // Append API key to URL for authentication during download | ||
| const urlWithAuth = apiKey | ||
| ? `${generatedSample.video.uri}${generatedSample.video.uri.includes('?') ? '&' : '?'}key=${apiKey}` | ||
| : generatedSample.video.uri; | ||
| // Append the API key to the download URL for authentication, but only | ||
| // when the response-supplied URI stays on the provider's own origin — | ||
| // otherwise the key would leak to whatever host the response names. | ||
| const urlWithAuth = | ||
| apiKey && isSameOrigin(generatedSample.video.uri, this.config.baseURL) | ||
| ? `${generatedSample.video.uri}${generatedSample.video.uri.includes('?') ? '&' : '?'}key=${apiKey}` | ||
| : generatedSample.video.uri; | ||
@@ -289,0 +293,0 @@ videos.push({ |
@@ -279,3 +279,32 @@ export type PartialArg = { | ||
| const hasOwn = Object.prototype.hasOwnProperty; | ||
| /** | ||
| * Checks only direct properties so path traversal never follows the prototype chain. | ||
| */ | ||
| function hasOwnProperty( | ||
| obj: Record<string | number, unknown>, | ||
| key: string | number, | ||
| ): boolean { | ||
| return hasOwn.call(obj, key); | ||
| } | ||
| /** | ||
| * Defines path values as own data properties so special keys like `__proto__` | ||
| * cannot invoke prototype setters while accumulating streamed arguments. | ||
| */ | ||
| function defineOwnProperty( | ||
| obj: Record<string | number, unknown>, | ||
| key: string | number, | ||
| value: unknown, | ||
| ): void { | ||
| Object.defineProperty(obj, key, { | ||
| value, | ||
| enumerable: true, | ||
| configurable: true, | ||
| writable: true, | ||
| }); | ||
| } | ||
| /** | ||
| * Traverses a nested object along the given path segments and returns the leaf value. | ||
@@ -293,3 +322,5 @@ * | ||
| if (current == null || typeof current !== 'object') return undefined; | ||
| current = (current as Record<string | number, unknown>)[seg]; | ||
| const currentRecord = current as Record<string | number, unknown>; | ||
| if (!hasOwnProperty(currentRecord, seg)) return undefined; | ||
| current = currentRecord[seg]; | ||
| } | ||
@@ -314,8 +345,8 @@ return current; | ||
| const nextSeg = segments[i + 1]; | ||
| if (current[seg] == null) { | ||
| current[seg] = typeof nextSeg === 'number' ? [] : {}; | ||
| if (!hasOwnProperty(current, seg) || current[seg] == null) { | ||
| defineOwnProperty(current, seg, typeof nextSeg === 'number' ? [] : {}); | ||
| } | ||
| current = current[seg] as Record<string | number, unknown>; | ||
| } | ||
| current[segments[segments.length - 1]] = value; | ||
| defineOwnProperty(current, segments[segments.length - 1], value); | ||
| } | ||
@@ -322,0 +353,0 @@ |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
2370878
0.41%27206
0.33%+ Added
- Removed