AI SDK 如何校验 Provider 响应中的 URL 以防止 SSRF 攻击 📅 发布时间:2026/9/13 20:12:56 👁 浏览次数: AI SDK 如何校验 Provider 响应中的 URL 以防止 SSRF 攻击【免费下载链接】aiThe AI Toolkit for TypeScript. From the creators of Next.js, the AI SDK is a free open-source library for building AI-powered applications and agents项目地址: https://gitcode.com/GitHub_Trending/ai/ai很多 AI Provider 会在响应体里返回一个 URL——待下载的生成图片、音频、视频或者用于轮询任务状态的地址。AI SDK 会在服务端代你抓取这些 URL 并把结果交回你的代码。由于 URL 来自外部服务一个被攻破或被篡改的 Provider 可以把它指向云元数据端点如http://169.254.169.254/…、内网主机http://10.0.0.5/…或localhost从而让你的服务器发起针对内网的请求即 SSRF 攻击。AI SDK 的应对方式是在抓取之前校验每一个来自响应的 URL。这件事在 Provider 包内部自动发生你不需要配置任何东西。本文说明校验覆盖了哪些环节、被拦截的 URL 在你的代码里如何表现、非 Node.js 运行时的限制以及如何按官方建议进一步加固部署。SDK 自动校验的内容当 SDK 抓取一个取自 Provider 响应的 URL 时会执行以下检查完整说明见 Secure URL Fetching 文档拒绝私有、环回和链路本地目标——IPv4 的10/8、172.16/12、192.168/16、127/8、169.254/16、CGNAT、多播等区间及对应的 IPv6 区间外加localhost和.local域名非http(s)协议同样被拒绝。对每一个重定向跳重新校验——一个 URL 本身合法、随后重定向到内网地址的情况会被拦截SDK 不会盲目跟随重定向。在 Node.js 上于连接时校验 DNS——每一个解析出的地址都会被检查并且 socket 会被固定到已校验的 DNS 结果上因此 DNS rebinding 无法在校验与连接之间引入另一个地址。剥离高危请求头——代理转发、云元数据和 Cookie 类请求头在发出请求前被移除。跨源丢弃凭据——调用方请求头Authorization、Cookie以及各 Provider 的 API-key 头不会发往与 Provider 不同源的宿主跨源重定向会丢弃除 user-agent 以外的全部这些头。被拦截的 URL 会以DownloadError的形式抛到你的代码中。两个需要注意的例外路径自托管与本地端点。与你配置的 Provider 端点同源的 URL例如自定义baseURL指向自托管或localhost部署会豁免上述检查——它指向的正是你明确要求 SDK 访问的主机任务状态轮询同样适用。任何离开该源的重定向仍会在发出前被校验。带认证的任务状态轮询。Provider 可以从你配置的 API 端点构造第一个 URL。SDK 对初始请求信任这个已配置的源但会手动跟随并校验之后离开该源的每一个重定向。文档指出 MiniMax、Kling AI 和 ByteDance 的视频轮询走的就是这条受保护路径。在代码中识别被拦截的下载校验拦截、下载失败、超出大小限制等情况统一表现为DownloadError。你可以用静态方法isInstance判断并单独处理完整属性说明见 AI_DownloadError 参考import { DownloadError } from ai; if (DownloadError.isInstance(error)) { // error.url —— 下载失败的 URL // error.statusCode / error.statusText —— 服务端返回的状态码与状态文本可选 // error.cause —— 导致下载失败的底层错误可选 // error.message —— 下载失败详情自动生成可选 }例如语音转写场景传入 URL 时audio: new URL(https://example.com/audio.mp3)SDK 默认以 2 GiB 大小限制下载超限时抛出的就是DownloadError可以按上面的方式捕获并记录error.message。这也是判断URL 被安全校验拦截与普通网络错误的实际落点。非 Node.js 运行时的差异默认行为针对 Node.js校验用的下载 fetch 通过node:dns与undici连接器钩子在连接时校验每一个解析出的地址连接器直接使用这些结果建立连接同时堵死 hostname-to-private-IP 和 DNS rebinding 两类绕过。由此推出两条部署约束如果你注入或全局替换了fetch等价的 DNS 校验与连接固定由你的实现负责SDK 不再替你兜底。其他运行时不暴露 Node 的 DNS/socket 钩子在这些运行时部署服务端时应当用网络层手段限制到私有、环回、链路本地和云元数据区间的出站流量。进一步加固部署官方建议对服务端会抓取 Provider 返回的 URL的部署尽量同时采用以下两种方式完整命令与代码见 Secure URL Fetching 文档方式一在网络层限制出站流量在服务器的网络层拒绝发往169.254.0.0/16、RFC-1918 区间和环回地址的出站流量。文档明确指出这是最稳健的控制手段因为它独立于应用代码——即使应用层校验出现缺口流量也出不去。方式二加固注入的fetchNode.js 默认路径已经做了连接期固定如果你注入或全局替换了fetch官方文档给出的做法是用一个undiciAgent承载它在connect.lookup中校验解析出的 IP只允许连接安全地址。文档示例代码如下import { Agent, fetch as undiciFetch } from undici; import { lookup } from node:dns; // Your own check that returns true for private/loopback/link-local addresses. declare function isUnsafeAddress(ip: string): boolean; const safeLookup: typeof lookup (hostname, options, callback) { lookup(hostname, options as any, (err, address, family) { if (!err typeof address string isUnsafeAddress(address)) { callback(new Error(Refusing to connect to ${address}), , 0); return; } (callback as any)(err, address, family); }); }; const safeDispatcher new Agent({ connect: { lookup: safeLookup } }); const safeFetch: typeof fetch (input, init) undiciFetch(input, { ...init, dispatcher: safeDispatcher }) as any;注意示例中的isUnsafeAddress是一个需要你自己实现的判断函数契约如文档注释所述对私有/环回/链路本地地址返回true。其余代码可直接使用。然后把safeFetch传给 Provider 构造函数例如import { createFal } from ai-sdk/fal; const fal createFal({ fetch: safeFetch });最后一条原则SDK 的 URL 校验与你自定义 fetch 的连接期固定是互补关系文档明确要求两者都保留。边界与延伸阅读校验只针对URL 来自响应体的场景主机固定由你的配置决定的请求validateUrl: false路径不会触发这条校验链。如果你在开发 Provider 包validateUrl、trustedOrigin、credentialedOrigin的取舍规则见仓库内的 Secure URL handling 贡献指南。实现入口在核心包的下载工具 download.ts它调用ai-sdk/provider-utils的fetchWithValidatedRedirects完成带重定向校验的抓取相关实现位于 packages/provider-utils。对自托管含localhost的 Replicate 兼容服务端、内部 fal 部署用户你的端点天然与配置的baseURL同源不会被误拦但离开该源的任何重定向仍会被校验遇到DownloadError时应先确认 Provider 是否返回了异常的重定向目标。【免费下载链接】aiThe AI Toolkit for TypeScript. From the creators of Next.js, the AI SDK is a free open-source library for building AI-powered applications and agents项目地址: https://gitcode.com/GitHub_Trending/ai/ai创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考