[Bug]: Zero-cost budget bypass leaks unbounded spend when the free model has a paid fallback

当 LiteLLM 中配置了零成本模型(如本地 Ollama)并为它设置了付费的 fallback 目标时,请求会在 auth 阶段被判定为“零成本模型”从而跳过全部预算检查( skip_budget_checks = True ),随后在 router 阶段 fallback 到付费部署,导致已耗

快速结论:当 LiteLLM 中配置了零成本模型(如本地 Ollama)并为它设置了付费的 fallback 目标时,请求会在 auth 阶段被判定为“零成本模型”从而跳过全部预算检查(skip_budget_checks = True),随后在 router 阶段 fallback 到付费部署,导致已耗尽 max_budget 的 key 仍可无限消费。优先排查 fallback 链路上是否存在付费目标。

适用环境:Issue 中明确涉及 LiteLLM(含 proxy/auth 与 router 模块)、litellm_settings.fallbacksgeneral_settings 配置。Issue 未提供操作系统、Python、CUDA、显卡或具体依赖版本信息,故不补写。

最快修复方案:升级到包含 #41379 的 LiteLLM 版本,该 PR 在每次 fallback 目标被尝试前重新执行预算检查(fallback_budget_check),且按 Issue 说明“Enforcement is on by default”。暂无确认的一步配置级修复方案。

注意事项:#41379 自述为 draft、仍在等待端到端 proof-of-fix 运行,且最初的“opt-in vs default-on”争议在评论中尚未完全定论;评论中提到其范围目前仅覆盖 key + user 预算。若无法升级,可在应用层对 fallback 付费目标做额度兜底,但这不是 Issue 中验证过的方案。

问题场景

用户在 LiteLLM proxy 中配置了一个 free-model(例如 ollama/llama2input_cost_per_token: 0output_cost_per_token: 0),并通过 litellm_settings.fallbacks 为该模型组配置了付费 fallback 目标。当 primary 的零成本部署上游失败(如 429、quota exhausted)时,请求会被 router 转发到付费部署。由于预算门禁只在 auth 阶段对“请求的模型组”执行过一次,fallback 到付费部署时没有任何预算复核,用户即使 max_budget 已耗尽,仍可继续产生消费。

报错原文

[Bug]: Zero-cost budget bypass leaks unbounded spend when the free model has a paid fallback

Skipping all budget checks for zero-cost model

原因分析

LiteLLM 的零成本预算绕过逻辑 _is_model_cost_zero()(位于 litellm/proxy/auth/auth_checks.py)只检查 get_model_group_info(model_group=<requested model>),从不查阅 litellm_settings.fallbacks。当命中零成本判定后,user_api_key_auth.py 会设置 skip_budget_checks = True,key、user、team、end-user、org 及 per-model 预算全部被豁免,reserve_budget_for_request 也被完全跳过。

问题在于该判定基于“被请求的模型组”,而实际的计费主体是 fallback 后真正执行的部署。评论中将其概括为“决策作用域错误(wrong scope)”:预算预留应基于“解析后的模型(resolved model)”,而不是请求时的模型身份。消费在调用后仍会被记录(spend logs 可见),但从未被强制执行(enforced)。

Issue 指出,同类问题在模型访问控制上已经解决:litellm/proxy/auth/fallback_model_access.py 通过 Router.__init__(fallback_access_check=...)run_async_fallback 中对每个 fallback 目标重新做访问校验,由 general_settings.enforce_fallback_model_access 启用。而预算没有对应机制,这一不对称即为该 bug。

环境排查

  • 确认 LiteLLM 版本是否已包含 #41379(含 fallback_budget_check 的实现)。
  • 确认 model_list 中零成本模型组的 input_cost_per_token/output_cost_per_token 是否被设置为 0。
  • 确认 litellm_settings.fallbacks(及同类 router_settings.fallbacks)中该零成本模型组是否配置了付费目标。
  • 确认 general_settings 中是否启用了 enforce_fallback_model_access(该机制存在但并不解决预算问题)。
  • 检查 spend logs 中是否出现了超出 max_budget 的记录,以判断是否已触发该绕过。
  • Issue 未提供 Python、CUDA、PyTorch、显卡等环境信息,无需据此排查。

解决步骤

  1. 升级 LiteLLM 到包含 #41379 的版本,该 PR 在 fallback 目标被执行前重新检查预算(fallback_budget_check,作为 fallback_access_check 的预算兄弟机制),并按 Issue 说明默认开启。
  2. 若暂时无法升级,作为临时缓解,可在 litellm_settings.fallbacks 中避免为零成本模型组配置付费回退目标;或对该场景的 key 额外设置外部额度监控(此为缓解设想,Issue 未验证)。
  3. 升级后核实预算复核是否覆盖所需预算维度:评论中指出 #41379 当前“scoped to key + user budgets for now”,team、end-user、org 及 per-model 预算是否也被覆盖需以实际版本为准。
  4. 关注 #41379 从 draft 转正式合并的进展,Issue 本身在 2026-09-16 已关闭,说明修复已落地;若使用旧版本请以升级为准。

验证方法

配置一个 free-model(零成本)并为其设置付费 fallback,使用一个 max_budget 已耗尽的 key 发起请求,使 primary 的零成本部署失败从而触发 fallback。预期修复后该 fallback 目标会因预算检查被拒绝(或请求返回预算相关错误),而不是继续产生消费;同时 spend logs 中不应再出现无约束增长的付费消费记录。也可参考 #41379 计划中的端到端 proof-of-fix 运行作为对照。

参考来源

BerriAI/litellm #41344

BerriAI/litellm #41379(修复 PR,draft)

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 24814

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注