transports/v2.2.1
Tencent-Hunyuan/HY-Motion-1.0transports/v2.2.1Sep 18, 2026by akshaydeo
Upgrading?
AI Summary
Transport release addressing critical security vulnerabilities (SSRF, Resource ID Injection) and fixing provider integration issues including Claude Code thread continuations and Bedrock service tiers.
Key Highlights
- Fixes critical Bedrock S3 SSRF vulnerability via bucket name validation
- Fixes Resource ID Path Injection vulnerability
- Fixes Claude Code thread continuation failures behind key rotation
- Adds user attribution to Prometheus metrics
New Features
- Virtual Key Assignees and Expanded Search
- User Attribution in Prometheus Metrics
- Prompt Cache Breakpoints Capability
- MCP Observed Latency tracking
Full Release Notes
## Bifrost HTTP Transport Release v2.2.1
## ✨ Features
- **Virtual Key Assignees and Expanded Search** - The virtual key list resolves `assigned_user` for every row via a single batch lookup, and VK search matches team, customer and user names in addition to key fields, so keys can be found by who owns them (#7225, #7226)
- **User Attribution in Prometheus Metrics** - The telemetry plugin's metrics export includes user id and user name labels, so per-user usage and error rates can be graphed and alerted on directly (#7267)
- **Prompt Cache Breakpoints Capability** - A `SupportsPromptCacheBreakpoints` model cap with a name-based fallback for OpenRouter gates `prompt_cache_breakpoint` forwarding, so OpenRouter's non-Claude models stop rejecting requests that carry it (#7261, #7262)
- **MCP Observed Latency** - Native (observed) MCP tool-call latency from `observed_latency_ms` is surfaced in the logs duration column and detail sheet, kept clearly distinct from true execution time and never fabricating a synthetic start timestamp on the timeline (#7271)
## 🐞 Fixed
- **Resource ID Path Injection** - Caller-supplied resource IDs (batch, file, video, container, response IDs, cached content names) were interpolated into outbound URL paths unvalidated; a crafted ID with `../`, `?`, `#`, percent-encoded bytes or control characters could redirect the request to an unintended upstream endpoint. A central `EscapeResourceID` helper validates and escapes every such ID (#7307, #7310)
- **Bedrock S3 SSRF** - A caller-supplied `s3://` file ID or `s3_bucket` param could control the upstream host, since S3 virtual-hosted URLs are built as `https://{bucket}.{s3host}/{key}`; a bucket like `127.0.0.1:PORT#` opened a SigV4-signed TLS connection to a caller-chosen host. Bucket names are now validated with a DNS-compatible regex (#7315)
- **Caller-Forged Billing Idempotency** - The billing-idempotency key was `(RequestID, AttemptNumber)`, and `RequestID` may come from the caller's `x-request-id` header, so two unrelated requests sharing a deliberately chosen ID collided and the second was silently never charged. An internally minted `BillingNonce` is mixed into the key, making it unforgeable (#7303)
- **Abandoned Non-Streaming Request Hung Forever** - The worker kept a `ctx.Done()` arm on an already-claimed delivery send, a regression from the #6972 delivery fix, so a non-streaming caller could hang indefinitely (#7313)
- **Repeated Empty Thinking Blocks** - Streaming chat chunks emitted empty reasoning/message fields on every content delta, which clients rendered as repeated empty thinking blocks (#7318)
- **Claude Code Thread Continuations Failed Behind Key Rotation** - Claude Code's server-side conversation threads are bound to the upstream account that creates them, and Bifrost's per-request key selection, retries and fallbacks cannot keep a continuation on that account, so `thread: {"type": "continue"}` requests failed with `thread_not_found` (about half the time on a two-key config). The Anthropic integration now declares itself stateless: continuations are refused before the provider call with a 400 whose `details.error_code` is `thread_unsupported_request`, which makes the client resend the turn in full and stop sending the thread field for the rest of the session, and the provider raw-body path strips `thread` from create requests so no orphaned thread state accumulates upstream. Token counting is never refused (#7274)
- **Gemini Flash-Lite Minimal Thinking Promoted to Low** - Normalized `gemini-3.1-flash-lite` requests silently promoted `minimal` thinking to `low` on both Gemini and Vertex; the text model's four supported levels are now registered, preserving the image variant's separate restrictions (#7288) (thanks [@Javtor](https://github.com/Javtor)!)
- **Config.json Virtual Key Limits Broke Under UI Edits** - VK rate limits and budgets created via the config.json standalone-limits flow and then edited through the UI produced duplicate, conflicting ownership records (standalone budgets owned directly by the VK, plus orphaned UUID rate-limit rows created by the UI). Migration `migrate_vk_standalone_limits_to_model_configs` consolidates ownership into VK-scoped model configs while preserving usage counters, and the write paths stop creating the divergent rows (#7291)
- **Bedrock Service Tier Rejections** - Service tier forwarding for Bedrock (Converse and Mantle paths) sent whatever tier was requested; it is now gated on explicit model capability metadata, failing closed when none exists, so models that do not support the requested tier stop rejecting the request (#7266)
- **Anthropic Root-Level Tool Schema Compositions** - Anthropic rejects `oneOf`/`anyOf`/`allOf` at the root of a tool's `input_schema` but accepts them inside properties; root-level compositions are now rewritten into a flat object schema before dispatch, unblocking tools like Codex's `automation_update` (#7265)
- **GenAI Streaming TTS** - Speech stream chunks routed through the `/genai` integration had no converter registered; `ToGeminiSpeechStreamResponse` now serves streaming TTS, and the streaming router returns a clean error instead of panicking when any stream converter is missing (#7248)
- **xAI Usage and Cost** - xAI reports visible and reasoning completion tokens separately; `completion_tokens` now folds reasoning in so `prompt_tokens + completion_tokens = total_tokens` holds, and streaming cost normalization preserves xAI's authoritative `cost_in_usd_ticks` to the terminal usage chunk instead of falling back to catalog pricing (#7245, #7250)
- **OpenAI-Only `search_content_types` Forwarded Everywhere** - `search_content_types` on `web_search` tools is an OpenAI-specific extension; it is now gated behind a per-provider capability check so Bedrock and other OpenAI-compatible backends receive a clean `web_search` tool without the field (#7244)
- **Claude Code `diagnostics` Field Rejected by Non-Native Providers** - Claude Code sends `diagnostics.previous_message_id` on every request; on the typed-sanitizer path Bedrock, Vertex and Azure returned 400 `diagnostics: Extra inputs are not permitted`. The field is stripped for providers that do not support it (#7243)
- **Unreadable Bedrock Error Logs** - AWS returns errors in a flat `{"message": ..., "__type": ...}` shape the shared Anthropic/OpenAI parsers never looked at, so Bedrock errors were logged with no human-readable reason; the root-level message now seeds `BifrostError`, and the logs UI falls back to showing the raw provider error body when no message could be extracted (#7221, #7222)
- **Anthropic `container` Param Dropped** - The string-form `container` param on `/anthropic/v1/messages` was silently dropped, so container reuse provisioned a fresh container every time; it is now carried through the round trip (#5829) (thanks [@AdityaPainuli](https://github.com/AdityaPainuli)!)
- **Responses API Finish Reason Missing From OTEL Spans** - `gen_ai.response.finish_reason` / `finish_reasons` are now emitted on the `llm.call` span for `/v1/responses` requests, so refusals are visible to OTEL consumers, matching the chat path (#7205) (thanks [@bkfl-notai](https://github.com/bkfl-notai)!)
- **Cohere Fallback Response Shape** - The Cohere-compatible route returned the raw Bifrost normalized response when a fallback served the request from a non-Cohere provider, which the Cohere SDK failed to parse; responses are now converted to the Cohere v2 shape (`message`, `finish_reason`) (#7198)
- **Skill Serving Race** - Fixed a race condition in the skill serving handler
- **Log and Dashboard Label Truncation** - Long model and provider labels in the logs table and dashboard charts truncate from the start so the distinctive suffix stays visible, the logs model column is wider, the search field border and icon spacing are cleaned up, and key picker options are keyed by id so duplicate labels stop highlighting together (#7215, #7216, #7217, #7269, #7297)
## 🗄️ Database Migrations
- **migrate_vk_standalone_limits_to_model_configs** - Consolidates virtual key standalone budgets and rate limits into VK-scoped model configs: standalone budgets are re-pointed to the VK's top-level model config (created if missing, usage preserved), orphaned duplicate UUID rate-limit rows created by the UI are deleted with the model config re-pointed to the canonical config.json row, and `vk.rate_limit_id` is cleared.
## 🐙 Closed GitHub Issues
- [#123](https://github.com/maximhq/bifrost/issues/123) - Files API Support
- [#5707](https://github.com/maximhq/bifrost/issues/5707) - string-form `container` param on /anthropic/v1/messages is silently dropped - container reuse provisions a fresh container
- [#7204](https://github.com/maximhq/bifrost/issues/7204) - Responses API path never sets gen_ai.response.finish_reason in OTEL traces (refusals invisible to observability)
- [#7287](https://github.com/maximhq/bifrost/issues/7287) - Gemini 3.1 Flash-Lite minimal thinking is silently promoted to low
- [#7294](https://github.com/maximhq/bifrost/issues/7294) - Streaming chat chunks emit empty reasoning/message fields on every content delta, causing repeated thinking blocks
- [#7308](https://github.com/maximhq/bifrost/issues/7308) - non-streaming caller hangs forever - worker keeps a ctx.Done() arm on a claimed delivery send (regression from #6972)
### Installation
#### Docker
```bash
docker run -p 8080:8080 maximhq/bifrost:v2.2.1
```
#### Binary Download
```bash
npx @maximhq/bifrost --transport-version v2.2.1
```
### Docker Images
- **`maximhq/bifrost:v2.2.1`** - This specific version
- **`maximhq/bifrost:latest`** - Latest version (updated with this release)
---
_This release was automatically created with dependencies: core `v1.9.1`, framework `v1.7.1`. All plugins have been validated and updated._Related Repositories
public-apis/public-apis★ 491,193
A collective list of free APIs
NousResearch/hermes-agent★ 256,048
The agent that grows with you
yt-dlp/yt-dlp★ 200,218
A feature-rich command-line audio/video downloader
microsoft/markitdown★ 191,539
Python tool for converting files and office documents to Markdown.
Significant-Gravitas/AutoGPT★ 187,701
AutoGPT is the vision of accessible AI for everyone, to use and to build on. Our mission is to provide the tools, so that you can focus on what matters.