chore(release): backport proxy request-handling maintenance and refresh runtime deps for 1.96.1 - #36494
Conversation
fix(proxy)!: apply request-parameter checks consistently across body, path and form inputs (cherry picked from commit c898d34)
Greptile SummaryThis patch backports request-parameter safety handling to the 1.96 release line, updates the health-check credential merge, and cuts version 1.96.1
Confidence Score: 4/5The PR appears safe to merge after removing the two newly added inline source comments The request guards, health-check merge, and dependency refresh have no established blocking defect; the only accepted issue is a repository convention violation on two import lines Files Needing Attention: litellm/proxy/health_endpoints/_health_endpoints.py
|
| Filename | Overview |
|---|---|
| litellm/proxy/auth/auth_utils.py | Adds bracket-notation metadata to the centralized banned-parameter validation using the same parser as its downstream consumer |
| litellm/proxy/common_request_processing.py | Extends the existing URL-valued destination guard to path and query model inputs before effective model selection |
| litellm/proxy/health_endpoints/_health_endpoints.py | Removes configured connection details when a request supplies its own guarded parameters, with a non-blocking source-comment convention violation |
| litellm/proxy/image_endpoints/endpoints.py | Rejects URL-valued Azure image deployment path parameters before provider dispatch |
| litellm/proxy/litellm_pre_call_utils.py | Extracts the existing single-field URL destination validation without changing its parsing or allowlist semantics |
| uv.lock | Advances the project version and updates only pypdf from 6.14.2 to 6.15.0 within the existing dependency range |
| osv-scanner.toml | Removes the two pypdf vulnerability exceptions addressed by the lockfile upgrade |
Reviews (1): Last reviewed commit: "chore: refresh uv.lock for 1.96.1" | Re-trigger Greptile
| UserAPIKeyAuth, | ||
| WebhookEvent, | ||
| ) | ||
| from litellm.proxy.auth.auth_utils import ( |
There was a problem hiding this comment.
The inline explanations added to this import and the corresponding import on line 49 violate the repository policy against adding source comments without an explicit request, creating maintenance text that should be removed.
Context Used: CLAUDE.md (source)
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
….2) (#315) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [ghcr.io/berriai/litellm](https://images.chainguard.dev/directory/image/wolfi-base/overview) ([source](https://github.com/BerriAI/litellm)) | patch | `v1.96.0` → `v1.96.2` | --- ### Release Notes <details> <summary>BerriAI/litellm (ghcr.io/berriai/litellm)</summary> ### [`v1.96.2`](https://github.com/BerriAI/litellm/releases/tag/v1.96.2) [Compare Source](BerriAI/litellm@v1.96.2...v1.96.2) ##### Verify Docker Image Signature All LiteLLM Docker images are signed with [cosign](https://docs.sigstore.dev/cosign/overview/). Every release is signed with the same key introduced in [commit `0112e53`](BerriAI/litellm@0112e53). **Verify using the pinned commit hash (recommended):** A commit hash is cryptographically immutable, so this is the strongest way to ensure you are using the original signing key: ```bash cosign verify \ --key https://raw.githubusercontent.com/BerriAI/litellm/0112e53046018d726492c814b3644b7d376029d0/cosign.pub \ ghcr.io/berriai/litellm:v1.96.2 ``` **Verify using the release tag (convenience):** Tags are protected in this repository and resolve to the same key. This option is easier to read but relies on tag protection rules: ```bash cosign verify \ --key https://raw.githubusercontent.com/BerriAI/litellm/v1.96.2/cosign.pub \ ghcr.io/berriai/litellm:v1.96.2 ``` Expected output: ``` The following checks were performed on each of these signatures: - The cosign claims were validated - The signatures were verified against the specified public key ``` *** ##### What's Changed - chore(release): backport proxy request-handling maintenance and refresh runtime deps for 1.96.1 by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36494](BerriAI/litellm#36494) - bump: version 1.96.1 → 1.96.2 (1.96.1 burned by the PyPI storage failure) by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36570](BerriAI/litellm#36570) **Full Changelog**: <BerriAI/litellm@v1.96.0...v1.96.2> ### [`v1.96.2`](https://github.com/BerriAI/litellm/releases/tag/v1.96.2) [Compare Source](BerriAI/litellm@v1.96.0...v1.96.2) ##### Verify Docker Image Signature All LiteLLM Docker images are signed with [cosign](https://docs.sigstore.dev/cosign/overview/). Every release is signed with the same key introduced in [commit `0112e53`](BerriAI/litellm@0112e53). **Verify using the pinned commit hash (recommended):** A commit hash is cryptographically immutable, so this is the strongest way to ensure you are using the original signing key: ```bash cosign verify \ --key https://raw.githubusercontent.com/BerriAI/litellm/0112e53046018d726492c814b3644b7d376029d0/cosign.pub \ ghcr.io/berriai/litellm:v1.96.2 ``` **Verify using the release tag (convenience):** Tags are protected in this repository and resolve to the same key. This option is easier to read but relies on tag protection rules: ```bash cosign verify \ --key https://raw.githubusercontent.com/BerriAI/litellm/v1.96.2/cosign.pub \ ghcr.io/berriai/litellm:v1.96.2 ``` Expected output: ``` The following checks were performed on each of these signatures: - The cosign claims were validated - The signatures were verified against the specified public key ``` *** ##### What's Changed - chore(release): backport proxy request-handling maintenance and refresh runtime deps for 1.96.1 by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36494](BerriAI/litellm#36494) - bump: version 1.96.1 → 1.96.2 (1.96.1 burned by the PyPI storage failure) by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​36570](BerriAI/litellm#36570) **Full Changelog**: <BerriAI/litellm@v1.96.0...v1.96.2> </details> --- ### Configuration 📅 **Schedule**: (in timezone America/New_York) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about these updates again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate CLI](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC43LjQiLCJ1cGRhdGVkSW5WZXIiOiI0NC43LjQiLCJ0YXJnZXRCcmFuY2giOiJtYWluIiwibGFiZWxzIjpbInJlbm92YXRlL2NvbnRhaW5lciIsInR5cGUvcGF0Y2giXX0=--> Reviewed-on: https://git.greyrock.io/greyrock-labs/home-ops/pulls/315
TLDR
Problem this solves:
How it solves it:
Relevant issues
Patch release
1.96.1on top ofv1.96.0. The code commit is acherry-pick -xof a commit already merged tolitellm_internal_staging, so nothing here is new work written against the stable line#36011reachedlitellm_internal_stagingon 2026-08-05 and has been applied to every stable line from 1.88.x through 1.95.x. The 1.96.0 release branched before it arrived, so 1.96.x is the only line missing it. That ordering is the reason this PR exists: once 1.95.1 ships, a deployment upgrading to 1.96.0 would move from a line that has this change to one that does not, which is the opposite of what a version bump should meanLinear ticket
Pre-Submission checklist
Please complete all items before asking a LiteLLM maintainer to review your PR
@greptileaito re-request a review after pushing changes)Delays in PR merge?
If you're seeing a delay in your PR being merged, ping the LiteLLM Team on Slack (#pr-review).
Screenshots / Proof of Fix
Type
🧹 Refactoring
🚄 Infrastructure
Changes
fix(proxy)!: apply request-parameter checks consistently across body, path and form inputs (#36011)c898d341c0Adaptation notes
#36011diverges from staging in exactly two lines, both the same cause. Every other added and removed line is byte-identical to the staging commit, verified by diffing the two patches line by line rather than by reading the range-diffThe commit annotates with
Final, which neither_health_endpoints.pynorlitellm_pre_call_utils.pyimported on this line.Finaljoins each file's existingtypingimport rather than arriving on a second import line, matching how both files already source their generics. Unlike the 1.95.x backport, noMappingorIterableadaptation was needed; this line already imports those fromcollections.abcThe
_health_endpoints.pyhalf is load-bearing rather than cosmetic. That file gains a module-level_CONFIG_CONNECTION_FIELDS: Final[frozenset[str]], and module-level annotations are evaluated at import, so a missingFinalwould be an import-time failure at proxy startup rather than a lint finding. Thelitellm_pre_call_utils.pyhalf annotates a function-local, which Python does not evaluate, so there the same omission would surface only as a lint failureOne conflict resolved, in
litellm_pre_call_utils.py. The commit extracts the per-field logic intoreject_url_valued_destination, which computesallowed_hostsitself, leaving the local in_reject_url_valued_destinationsdead. Both sides delete that local; they differ only because this line's copy of the pre-image lacked theFinalannotation staging had already added. The post-image is identicalKnown behavior change
#36011is marked a breaking change upstream, so it is worth stating plainly what changes here/health/test_connectionmerges differently. Previously the proxy config was the base and request parameters layered on top, so a request could name a configured model, override one field, and still inherit the configured connection details. Now, if the request carries any of the request-parameter list, the configured connection fields are not carried into itA rough edge rides along unchanged from the upstream commit: the trigger is the full request-parameter list, but the fields dropped are the narrower connection set. So a request including a non-connection field such as
input_cost_per_tokenalso loses the configuredapi_baseandapi_key, leaving the probe with no endpoint and reporting a failed connection for a model that is fine.general_settings.allow_client_side_credentialsrestores the previous merge. This reproduces identically onlitellm_internal_staging, so it is not introduced by this backport; flagging it so any follow-up lands in the right placeThe other two changes are the intended effect of the commit. A URL-valued
modelsupplied through the URL path or query string is now handled the same way a URL-valuedmodelin the JSON body already was, and bracket-notation form fields such asmetadata[...]are now inspected the same way the equivalent JSON object already was. Every bracket payload now rejected was already rejected in its JSON form on 1.96.0Dependency refreshes
Routine maintenance of the image lockfile, moving to the smallest version that satisfies this line's ranges
pypdfThe regeneration moved nothing but its target, checked by parsing both locks rather than reading the diff.
pypdf>=6.12.0,<7.0already admits 6.15.0, so no manifest change is needed. The lock'sexclude-newerstamp also advances, which is inherent to re-resolving the relativeP3Dspan and is what makes 6.15.0 reachable at allosv-scanner.tomlloses its twopypdfentries in the same change. Both were written to expire on 2026-08-12 and both say to drop them alongside this bump, so leaving them would leave a stale claim in the tree. The file now matcheslitellm_internal_stagingbyte for byteThe remaining
diskcacheentry stays. No fixed release exists upstream, andlitellm_internal_stagingresolves the same version, so this line is not behind staging on itAfter this patch the line resolves every package at or below
litellm_internal_staging, checked by parsing both locks: 426 packages identical, 7 behind, none ahead. So upgrading from1.96.1to a later release never walks a dependency backwards, and the resulting lock carries the same residual scanner findings as staging itselfVerification
Run on a worktree cut from
stable/1.96.x, judged against a baseline captured on the untouched tipmodelcheck has no test of its own and was exercised directly rather than assumed. It is reached fromcommon_processing_pre_call_logic, which takesmodelas a parameter and is called with it from two call sites, behind the/engines/{model:path}/...and/openai/deployments/{model:path}/...routes. Driven directly, ordinary names such asgpt-4oandazure/my-deploymentpass through, URL-valued ones return 400, and theprovider_url_destination_allowed_hostsescape hatch both admits an allowlisted host and rejects it again once the allowlist is cleared, so the passing case is not vacuous_CONFIG_CONNECTION_FIELDSevaluates to a 36-entry frozenset, which proves the module-level annotation resolves at runtime rather than merely satisfying the linterruff format --checkreports all five touched files already formatted, andruff checkis clean on themuv lock --checkpasses, so the lock is not stale against the manifestThe gauntlet and a live-proxy replay were deliberately skipped for this line. The same commit has landed cleanly on eight other lines, so the open question here was cherry-pick fidelity rather than behavioral correctness, and that is what the divergence audit, symbol closure, and the revert check address
Final Attestation