v0 如何在不暴露 OAuth 令牌的前提下完成 Snowflake 身份验证
v0 的 Snowflake 集成面临一个核心矛盾:AI 生成的代码需要替用户访问数据库,但这些代码本身不可信,绝不能接触用户的 OAuth 令牌。v0 的解决办法是在沙箱外架设一个认证代理,沙箱内的代码照常使用标准 Snowflake 客户端,真正的令牌只在请求发出的瞬间由代理注入。本文拆解这套代理方案的设计思路,并解释为什么“用真令牌直接替换占位符”这种看似简单的做法反而会制造新的安全隐患。
矛盾:AI 代码需要访问数据,但不能持有凭证
v0 允许用户连接 Snowflake、浏览表结构、查询数据,并生成能直接运行在用户自己数据仓库上的应用。这些由模型写出来的代码,运行时没有人工审查,却必须自己完成 Snowflake 认证。与此同时,提示注入攻击(通过构造恶意输入诱导模型执行非预期操作)还可能让代码把能读到的数据全部外泄。
结论很明确:用户的 OAuth 令牌绝不能进入代码运行的环境。
所以 v0 选择了一条绕行的路:基于 Vercel Sandbox 防火墙,在 v0 沙箱前面构建一个 Snowflake 请求代理。沙箱里照常运行标准的 Snowflake 客户端,但真正的凭证放在沙箱之外的服务器代理侧,当请求发出的瞬间才解析出来。这样既能沿用现有的 Snowflake 客户端逻辑,又不会把用户凭证暴露给生成的代码。
真正难的部分是:代理应该在哪里安全地注入凭证?最直观的想法是“哪里有占位令牌就替换成真实令牌”,但这种方式本身就会制造新的凭证泄露点。
沙箱的局限:防得住外部,防不住内部
v0 在隔离的沙箱里运行生成的应用程序。沙箱隔离保护的是系统其余部分不被不可信代码破坏,但它保护不了沙箱内部的密钥。如果生成的程序能从文件系统里读到令牌,它就能把令牌复制进日志、塞进 API 响应、写进它生成的客户端代码,或直接发给另一台主机。沙箱限制了应用能触碰的系统资源,可一旦凭证本身已经躺在沙箱里,隔离就完全帮不上忙。
对 Snowflake 而言,这份凭证对应的是用户连接时所用的 Snowflake 角色。v0 要帮助用户探索和构建基于他们有权访问的数据的应用,但生成的代码不能仅仅因为需要认证,就拿到原始的云服务商凭证。
方案:所有 Snowflake 请求强制经过代理
沙箱本身无法直接与 Snowflake 通信。当沙箱里的代码向用户的 Snowflake 账户主机发起请求时,沙箱防火墙会把流量转发给 v0 Snowflake 代理。具体机制是:防火墙使用每个沙箱独有的证书颁发机构(CA)来终止 TLS 加密,这使得代理能够读取并改写原本被加密的流量。沙箱会自动信任这个 CA,因此 Snowflake SDK 和 CLI 会保持默认的证书验证方式运行,包括 OCSP(在线证书状态检查)在内。
请求到达代理后,代理依次完成四件事:
- 验证沙箱身份 —— 通过 OIDC 令牌确认请求来自哪个沙箱;
- 回溯对话上下文 —— 查询该沙箱所属的 v0 对话,恢复绑定到该对话的用户会话;
- 获取临时凭据 —— 为这个用户向 Snowflake 申请一个新的短期凭据;
- 限制目标主机 —— 代理从服务端凭据中推导出 Snowflake 账户主机,拒绝无效的账户 URL,而不是信任生成代码里写死的主机信息。
关键点在于:沙箱无法决定携带令牌的请求发往何处。 凭据被限制在用户已连接的 Snowflake 账户范围内,由代理来保证。
兼容现有客户端:用“假令牌”占位符蒙混过去
作为早期方案,该集成的第一个版本曾把用户的真实令牌写入沙箱内的 Snowflake 令牌文件,代理方案取代了这种做法。理想情况下,应该彻底从沙箱中移除令牌文件,但 Snowflake 客户端会根据不同的认证流程,期望凭据出现在不同位置。有些请求(如 Snowflake SQL API 调用)通过 Authorization: Bearer 标头进行身份认证;另一些客户端流程则读取本地令牌文件,把令牌作为登录请求的一部分发送。客户端完成身份认证后,后续请求使用 Snowflake 颁发的会话令牌,代理会原样放行。
为了兼容这些流程,v0 仍在沙箱里写入一个形似令牌的占位符。它是一个固定的、公开的 72 字节字符串,不授予任何访问权限,唯一的作用就是让现有的 Snowflake SDK 和 CLI 流程表现得像有令牌一样。代理绝不会仅凭占位符授权请求。相反,代理依赖沙箱的服务端身份,以及它与用户对话的绑定关系来授权。
对开发者的启示
从这套方案中能提炼出一个通用思路:在 AI 编程工具中,模型生成的代码天然不可信,凡是涉及用户凭证的环节,都应尽可能把“持有凭证”和“执行代码”分开。v0 的做法就像在所有外部请求路径上加了一道“安检门”——代码负责发起请求,代理负责决定是否放行,以及用谁的身份放行。这不仅适用于 Snowflake,也适用于其他需要 AI 代码代表用户访问的 SaaS 服务。