Skip to content

fix(proxy): restore pre-config-wins handling of pass-through endpoints - #43962

Merged
yuneng-berri merged 8 commits into
mainfrom
litellm_/jwt-forwarding-auth-false-ed0a9a
Oct 1, 2026
Merged

yuneng-berri merged 8 commits into
mainfrom
litellm_/jwt-forwarding-auth-false-ed0a9a

Conversation

@yuneng-berri

@yuneng-berri yuneng-berri commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

TLDR

Problem this solves:

  • Config pass-throughs with forward_headers: true stopped forwarding Authorization
  • Only with STORE_MODEL_IN_DB=true, starting in v1.103.0
  • UI create, update and delete of pass-throughs was rejected once the config declared any
  • os.environ/ pass-through targets were sent upstream unresolved and returned 500

How it solves it:

  • Puts pass-throughs back on their pre-refactor(proxy): make the config file win over the database #41779 handling, a targeted revert of that one key
  • The config file no longer owns general_settings.pass_through_endpoints, so the DB reader sees DB rows only
  • Each DB sync and every config reload again serve DB entries next to config entries on other paths
  • A UI pass-through write re-applies that merge right away, so config routes keep serving until the next sync

User Flow

Before: a team whose backend validates the caller's JWT gets "token not found" for every request through a config pass-through

  1. The admin declares a pass-through with forward_headers: true and auth: false in the config, with STORE_MODEL_IN_DB=true
  2. A client sends POST https://litellm-domain/copilot with Authorization: Bearer <jwt>
  3. The backend receives the request with no Authorization header and rejects it
  4. The admin tries to add another pass-through on the Admin UI and gets a 400 saying the config owns the key

After: the same request reaches the backend with the caller's JWT, and UI-created pass-throughs work next to the config ones

  1. Same config and env as before
  2. The client sends the same POST https://litellm-domain/copilot with Authorization: Bearer <jwt>
  3. The backend receives Authorization: Bearer <jwt> unchanged, right after boot and after every DB sync
  4. A pass-through created on the Admin UI is saved, serves traffic, and is listed next to the config ones

Affected release

Regression in v1.103.0-rc.1, still present on v1.103.0 and main

Linear ticket

Resolves LIT-9020

Pre-Submission checklist

  • I have added meaningful tests
  • The handful of test files covering my change pass locally
  • My PR passes all required CI/CD checks
  • My PR's scope is as isolated as possible; it only solves 1 specific problem
  • I have received a Greptile Confidence Score of at least 4/5 before requesting a maintainer review

Screenshots / Proof of Fix

Live proxy on Postgres with STORE_MODEL_IN_DB=True, PT_ENV_TARGET=http://127.0.0.1:9081/api/envtarget, and a local echo server on :9081 that returns the path and Authorization header it received. The same scenario script ran against both commits on a fresh database each time. Config:

model_list: []
general_settings:
  master_key: <master key>
  pass_through_endpoints:
    - path: "/copilot"
      target: "http://127.0.0.1:9081/api/copilot"
      forward_headers: true
      include_subpath: true
      auth: false
    - path: "/envtarget"
      target: "os.environ/PT_ENV_TARGET"
      auth: false
    - path: "/keyed"
      target: "http://127.0.0.1:9081/api/keyed"
      auth: true
      headers:
        litellm_user_api_key: "x-cfg-key"
    - path: "/defaultauth"
      target: "http://127.0.0.1:9081/api/defaultauth"
    - path: "/shared"
      target: "http://127.0.0.1:9081/api/shared-config"
      auth: false

Before (38b0762)

Config pass-through with forward_headers: true and auth: false

  1. Send the caller's JWT right after boot and the first DB sync; the echo upstream reports which Authorization it received

    curl -s -X POST "http://localhost:4091/copilot" -H "Authorization: Bearer caller-jwt" -H "content-type: application/json" -d '{"q":1}'
    {"path": "/api/copilot", "authorization": null} [HTTP 200]
    
  2. Same request after further DB sync cycles

    curl -s -X POST "http://localhost:4091/copilot" -H "Authorization: Bearer caller-jwt" -H "content-type: application/json" -d '{"q":1}'
    {"path": "/api/copilot", "authorization": null} [HTTP 200]
    

Config pass-through with an os.environ/ target

  1. Call the pass-through whose target is os.environ/PT_ENV_TARGET

    curl -s -X POST "http://localhost:4091/envtarget" -H "content-type: application/json" -d '{}'
    {"error":{"message":"/os.environ/PT_ENV_TARGET","type":"internal_server_error","param":null,"code":"500"}} [HTTP 500]
    

UI-created pass-through next to the config ones

  1. Create a pass-through through the Admin UI API

    curl -s -X POST "http://localhost:4091/config/pass_through_endpoint" -H "Authorization: Bearer $MASTER_KEY" -H "content-type: application/json" -d '{"path":"/snowflake","target":"http://127.0.0.1:9081/api/snowflake","auth":false}'
    {"detail":{"error":"general_settings key 'pass_through_endpoints' is set in the config file and cannot be changed here.", ...}} [HTTP 400]
    
  2. Call it right away

    curl -s -X POST "http://localhost:4091/snowflake" -H "content-type: application/json" -d '{}'
    {"detail":"Not Found"} [HTTP 404]
    
  3. List pass-throughs after a DB sync (summarized as path, is_from_config, auth)

    curl -s "http://localhost:4091/config/pass_through_endpoint" -H "Authorization: Bearer $MASTER_KEY"
    /copilot      is_from_config=false auth=false
    /defaultauth  is_from_config=false auth=true
    /envtarget    is_from_config=false auth=false target=os.environ/PT_ENV_TARGET
    /keyed        is_from_config=false auth=true
    /shared       is_from_config=false auth=false
    /shared       is_from_config=false auth=true
    /snowflake    is_from_config=false auth=false
    

After (b7fbc2f)

Config pass-through with forward_headers: true and auth: false

  1. Send the caller's JWT right after boot and the first DB sync; the echo upstream reports which Authorization it received

    curl -s -X POST "http://localhost:4092/copilot" -H "Authorization: Bearer caller-jwt" -H "content-type: application/json" -d '{"q":1}'
    {"path": "/api/copilot", "authorization": "Bearer caller-jwt"} [HTTP 200]
    
  2. Same request after further DB sync cycles

    curl -s -X POST "http://localhost:4092/copilot" -H "Authorization: Bearer caller-jwt" -H "content-type: application/json" -d '{"q":1}'
    {"path": "/api/copilot", "authorization": "Bearer caller-jwt"} [HTTP 200]
    

Config pass-through with an os.environ/ target

  1. Call the pass-through whose target is os.environ/PT_ENV_TARGET

    curl -s -X POST "http://localhost:4092/envtarget" -H "content-type: application/json" -d '{}'
    {"path": "/api/envtarget", "authorization": null} [HTTP 200]
    

UI-created pass-through next to the config ones

  1. Create a pass-through through the Admin UI API

    curl -s -X POST "http://localhost:4092/config/pass_through_endpoint" -H "Authorization: Bearer $MASTER_KEY" -H "content-type: application/json" -d '{"path":"/snowflake","target":"http://127.0.0.1:9081/api/snowflake","auth":false}'
    {"endpoints":[{"id":"<id>","path":"/snowflake","target":"http://127.0.0.1:9081/api/snowflake", ..., "auth":false, "is_from_config":false, ...}]} [HTTP 200]
    
  2. Call it right away

    curl -s -X POST "http://localhost:4092/snowflake" -H "content-type: application/json" -d '{}'
    {"path": "/api/snowflake", "authorization": null} [HTTP 200]
    
  3. List pass-throughs after a DB sync (summarized as path, is_from_config, auth)

    curl -s "http://localhost:4092/config/pass_through_endpoint" -H "Authorization: Bearer $MASTER_KEY"
    /copilot      is_from_config=true  auth=false
    /defaultauth  is_from_config=true  auth=true
    /envtarget    is_from_config=true  auth=false
    /keyed        is_from_config=true  auth=true
    /shared       is_from_config=false auth=true
    /snowflake    is_from_config=false auth=false
    

The same scenario, extended with UI update and delete, an unrelated /config/field/update write, /config/field/info, and a restart, matched pre-#41779 main call for call except one: a UI-created auth: false pass-through now serves right away instead of answering 401 until the next DB sync. It matched v1.102.2 for every config-only call

Type

🐛 Bug Fix

Caveats (if any)

Medium

Low

  • A UI-created auth: false pass-through now serves immediately; before it answered 401 until the next DB sync
  • Not verified live with enable_jwt_auth plus SERVER_ROOT_PATH, the customer's exact auth setup
    • Covered without JWT auth: forwarding, env targets, UI CRUD, restarts, field info

Final Attestation

  • The tests check the right things, including the edge cases, and regressions in the respective real-world customer use-cases are not possible after this PR

Note

Medium Risk
Changes proxy config resolution, pass-through route registration, and auth behavior when YAML and DB declare the same path; regression fix but affects request routing and admin settings APIs.

Overview
pass_through_endpoints is no longer config-owned when declared in YAML. The proxy treats it as a resource list (DB-primary): YAML no longer blocks Admin UI writes, and config reloads keep serving merged endpoint state instead of wiping runtime routes.

Serving model: DB-stored endpoints are registered from the database; config-file endpoints on other paths are merged in via _pass_through_endpoints_beside_db. Resolved config exposed to loaders includes that union. On the same path, the DB entry wins for what gets served (restores pre–#41779 behavior).

Lifecycle changes: _apply_pass_through_settings only re-initializes routes when the DB payload includes a list; deletes publish an empty DB slice while keeping config paths. General-settings create/update/delete for this field calls _serve_pass_through_endpoints immediately. GET /config/field/info uses _declared_general_setting so resource-list fields read from the DB row when appropriate.

Tests add broad integration coverage (forward_headers, env targets, UI CRUD, reload/sync) and update expectations where YAML+DB overlap now locks auth from the DB side.

Reviewed by Cursor Bugbot for commit e5ef842. Bugbot is set up for automated code reviews on this repo. Configure here.

Config-wins (#41779) made general_settings.pass_through_endpoints a config-owned key. The DB reader then got the config list back as if it were DB rows, re-registered each entry without forward_headers on every DB sync, and the stripped copy won the route lookup, so a config pass-through with forward_headers: true stopped forwarding Authorization. UI create, update and delete of pass-throughs were also rejected while the config declared any.

This puts pass-throughs back on their pre-#41779 path: the settings store no longer lets the config own the key, the config list is captured env-resolved at load_config, each DB sync merges DB entries with config entries on paths the DB does not declare, and /config/field/info reads the stored rows only. A UI pass-through write re-applies that merge immediately so the config entries stay served until the next sync.
@greptile-apps

greptile-apps Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 5/5

[High risk] Changes how pass-through endpoints are stored and resolved.

The latest changes appear safe to merge; no new actionable finding remains.

Summary

The PR separates config-declared pass-through endpoints from DB-owned settings, merges both sources for serving, and preserves active pass-through settings while a DB sync reads configuration. The latest commit adds the preservation step and a test for requests made during that read.

Reviews (6) · Last reviewed commit: "fix(proxy): keep pass-throughs served wh..."

Comment thread litellm/proxy/proxy_server.py
Comment thread litellm/proxy/proxy_server.py
Comment thread litellm/proxy/proxy_server.py Outdated
self.settings["pass_through_endpoints"] = _SETTINGS_LIST.validate_python(
(*db_endpoints, *config_endpoints_beside_db)
)
await initialize_pass_through_endpoints(pass_through_endpoints=_ENDPOINT_DICTS.validate_python(db_endpoints))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

High: Pass-through overrides authorize the wrong upstream

For a YAML POST /shared targeting a private upstream (auth: true) and a DB replacement POST /shared targeting a public upstream (auth: false), the merged auth list permits anonymous requests, but initialize_pass_through_endpoints() still registers both entries and the first-match registry selects the YAML entry registered at startup. An unauthenticated attacker can now reach the private upstream with its configured credentials; apply the same DB-wins filtering to route registration and remove shadowed YAML registry entries before publishing the replacement authentication policy.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pre-existing: pre-#41779 and v1.102 behave the same way. This PR reverts to that handling to fix a regression, so fixing route registration is a follow-up

@veria-ai

veria-ai Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

PR overview

The PR restores pre-configuration precedence handling for pass-through endpoints in the proxy, updating how YAML and database endpoint definitions are combined.

One issue has been addressed, but an authorization mismatch remains between merged endpoint settings and route registration. When a public database endpoint overrides a private YAML endpoint at the same path, anonymous requests can still be routed to the private upstream using its configured credentials. This leaves a concrete authentication bypass open until registration follows the same override rules and removes shadowed entries.

Open issues (1)

Fixed/addressed: 1 · PR risk: 8/10

@codspeed

codspeed Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 31 untouched benchmarks


Comparing litellm_/jwt-forwarding-auth-false-ed0a9a (2144aef) with main (ef6aa4a)1

Open in CodSpeed

Footnotes

  1. No successful run was found on main (2b19ddb) during the generation of this report, so ef6aa4a was used instead as the comparison base. There might be some changes unrelated to this pull request in this report. ↩

@codecov

codecov Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

get_config now returns DB pass-throughs plus config ones on other paths,
each DB sync republishes that merged list, and /config/field/info reads
pass_through_endpoints from the DB row so a UI write never drops stored
entries when models are not stored in the DB
@yuneng-berri

Copy link
Copy Markdown
Contributor Author

@greptileai please re-review the latest commit

Comment thread litellm/proxy/proxy_server.py Outdated
load_yaml cleared the runtime pass-through list, so auth: false routes
answered 401 while get_config awaited the database
A lagging read replica could return an older list, and the UI create and
edit flows write the whole field back
@yuneng-berri

Copy link
Copy Markdown
Contributor Author

@greptileai please re-review the latest commits

Comment thread litellm/proxy/config_resolvers/settings_store.py
@yuneng-berri

Copy link
Copy Markdown
Contributor Author

@greptileai please re-review

Comment thread litellm/proxy/config_resolvers/settings_store.py
The kept runtime list was merged as if it were DB entries, so an edited
config entry on the same path was dropped. Merge the stored DB row with
the fresh config instead, and give the field-info test mock a writer
@yuneng-berri

Copy link
Copy Markdown
Contributor Author

@greptileai please re-review the latest commit

@mateo-berri

Copy link
Copy Markdown
Contributor

bugbot run

@cursor cursor Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread litellm/proxy/proxy_server.py
Comment thread litellm/proxy/config_resolvers/settings_store.py
get_config resets the stored DB rows before reading them again, which
cleared the served pass-through list and made auth: false routes answer
401 for the length of the read
@yuneng-berri

Copy link
Copy Markdown
Contributor Author

@greptileai please re-review the latest commit

@yuneng-berri

Copy link
Copy Markdown
Contributor Author

bugbot run

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit e5ef842. Configure here.

@mateo-berri mateo-berri left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lgtm. Thanks!

basedpyright rejects a Final variable assigned inside a loop
@yuneng-berri
yuneng-berri merged commit 2eb2bf1 into main Oct 1, 2026
95 of 97 checks passed
@yuneng-berri
yuneng-berri deleted the litellm_/jwt-forwarding-auth-false-ed0a9a branch October 1, 2026 05:09
yuneng-berri added a commit that referenced this pull request Oct 1, 2026
…e_1_103_x

fix(proxy): backport #43962 to stable/1.103.x
jan-sauer-reef added a commit to jan-sauer-reef/litellm that referenced this pull request Oct 1, 2026
…ject_key_prefix

* upstream/main: (62 commits)
  fix(guardrails): scan Responses API input in Azure Prompt Shield (BerriAI#43786)
  feat(lens): investigate sampled traces and retain batch results (BerriAI#43942)
  fix(proxy): restore pre-config-wins handling of pass-through endpoints (BerriAI#43962)
  fix(cost-map): raise baseten DeepSeek-V4.1-Flash max output to 262144 (BerriAI#43916)
  chore(cost-map): add deprecation date for anthropic claude-sonnet-4-5 (BerriAI#43898)
  chore(cost-map): add fireworks inkling priority prices from the prices api (BerriAI#43949)
  feat(guardrails): honor litellm_params.timeout in every HTTP guardrail (BerriAI#43134)
  test(e2e): typed per-test metadata for the e2e suite (BerriAI#42044)
  fix(caching): write the response-cache SET to Redis at once instead of on the post-call batch (BerriAI#43973)
  feat(ui): filter tags by name and description on the Tag Management page (BerriAI#42949)
  feat(providers): add Cortecs as an OpenAI-compatible provider (BerriAI#43872)
  feat(e2e): record each e2e test's steps, starting with ProxyClient (BerriAI#42393)
  test(ci): repair stale tests and move retired OpenAI text-completion fixtures (BerriAI#43958)
  feat(proxy): record in spend logs whether a request used a client-forwarded Anthropic OAuth token (BerriAI#43063)
  fix(azure_storage): keep the DataLakeServiceClient alive until its TTL elapses (BerriAI#43082)
  chore(deps): bump gitpython and tornado, extend diskcache osv ignore to Nov 1 (BerriAI#43961)
  fix(guardrails): treat an unknown straiker api_version as unset instead of skipping the guardrail (BerriAI#43956)
  fix(azure_storage): name Data Lake objects without base64 padding or slashes (BerriAI#43914)
  fix(grayswan): send request conversation and tool calls to post-call monitor (BerriAI#43770)
  chore(cost-map): sync openrouter prices from the models API (BerriAI#43950)
  ...
stvnksslr pushed a commit to stvnksslr/litellm that referenced this pull request Oct 1, 2026
BerriAI#43962)

* fix(proxy): restore pre-config-wins handling of pass-through endpoints

Config-wins (BerriAI#41779) made general_settings.pass_through_endpoints a config-owned key. The DB reader then got the config list back as if it were DB rows, re-registered each entry without forward_headers on every DB sync, and the stripped copy won the route lookup, so a config pass-through with forward_headers: true stopped forwarding Authorization. UI create, update and delete of pass-throughs were also rejected while the config declared any.

This puts pass-throughs back on their pre-BerriAI#41779 path: the settings store no longer lets the config own the key, the config list is captured env-resolved at load_config, each DB sync merges DB entries with config entries on paths the DB does not declare, and /config/field/info reads the stored rows only. A UI pass-through write re-applies that merge immediately so the config entries stay served until the next sync.

* fix(proxy): keep config pass-throughs in every reload of the merged list

get_config now returns DB pass-throughs plus config ones on other paths,
each DB sync republishes that merged list, and /config/field/info reads
pass_through_endpoints from the DB row so a UI write never drops stored
entries when models are not stored in the DB

* fix(proxy): keep serving pass-throughs while the config file reloads

load_yaml cleared the runtime pass-through list, so auth: false routes
answered 401 while get_config awaited the database

* fix(proxy): read stored pass-throughs from the writer before a UI write

A lagging read replica could return an older list, and the UI create and
edit flows write the whole field back

* fix(proxy): apply config file pass-through auth changes on reload

The kept runtime list was merged as if it were DB entries, so an edited
config entry on the same path was dropped. Merge the stored DB row with
the fresh config instead, and give the field-info test mock a writer

* fix(proxy): keep pass-throughs served while a DB sync reads the database

get_config resets the stored DB rows before reading them again, which
cleared the served pass-through list and made auth: false routes answer
401 for the length of the read

* refactor(proxy): move the settings store reload out of the loop

basedpyright rejects a Final variable assigned inside a loop

(cherry picked from commit 2eb2bf1)
yuneng-berri added a commit that referenced this pull request Oct 1, 2026
#43962) (#44054)

* fix(proxy): restore pre-config-wins handling of pass-through endpoints

Config-wins (#41779) made general_settings.pass_through_endpoints a config-owned key. The DB reader then got the config list back as if it were DB rows, re-registered each entry without forward_headers on every DB sync, and the stripped copy won the route lookup, so a config pass-through with forward_headers: true stopped forwarding Authorization. UI create, update and delete of pass-throughs were also rejected while the config declared any.

This puts pass-throughs back on their pre-#41779 path: the settings store no longer lets the config own the key, the config list is captured env-resolved at load_config, each DB sync merges DB entries with config entries on paths the DB does not declare, and /config/field/info reads the stored rows only. A UI pass-through write re-applies that merge immediately so the config entries stay served until the next sync.

* fix(proxy): keep config pass-throughs in every reload of the merged list

get_config now returns DB pass-throughs plus config ones on other paths,
each DB sync republishes that merged list, and /config/field/info reads
pass_through_endpoints from the DB row so a UI write never drops stored
entries when models are not stored in the DB

* fix(proxy): keep serving pass-throughs while the config file reloads

load_yaml cleared the runtime pass-through list, so auth: false routes
answered 401 while get_config awaited the database

* fix(proxy): read stored pass-throughs from the writer before a UI write

A lagging read replica could return an older list, and the UI create and
edit flows write the whole field back

* fix(proxy): apply config file pass-through auth changes on reload

The kept runtime list was merged as if it were DB entries, so an edited
config entry on the same path was dropped. Merge the stored DB row with
the fresh config instead, and give the field-info test mock a writer

* fix(proxy): keep pass-throughs served while a DB sync reads the database

get_config resets the stored DB rows before reading them again, which
cleared the served pass-through list and made auth: false routes answer
401 for the length of the read

* refactor(proxy): move the settings store reload out of the loop

basedpyright rejects a Final variable assigned inside a loop

(cherry picked from commit 2eb2bf1)
devin-ai-integration Bot added a commit that referenced this pull request Oct 1, 2026
…ws on the hub

Main merges database pass-throughs with config file ones on other paths since
#43962, so a database write beside a config entry is accepted rather than
rejected as config-owned

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
doonga pushed a commit to greyrock-labs/home-ops that referenced this pull request Oct 2, 2026
…03.2) (#328)

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.103.1` → `v1.103.2` |

---

### Release Notes

<details>
<summary>BerriAI/litellm (ghcr.io/berriai/litellm)</summary>

### [`v1.103.2`](https://github.com/BerriAI/litellm/releases/tag/v1.103.2)

[Compare Source](BerriAI/litellm@v1.103.1...v1.103.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.103.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.103.2/cosign.pub \
  ghcr.io/berriai/litellm:v1.103.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): sync stable/1.103.x to v1.103.1 by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;43824](BerriAI/litellm#43824)
- fix(proxy): backport [#&#8203;40541](BerriAI/litellm#40541), [#&#8203;43642](BerriAI/litellm#43642), and [#&#8203;43656](BerriAI/litellm#43656) to stable/1.103.x for v1.103.2 by [@&#8203;devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#&#8203;43897](BerriAI/litellm#43897)
- fix(anthropic): backport [#&#8203;42152](BerriAI/litellm#42152) and [#&#8203;42288](BerriAI/litellm#42288) to stable/1.103.x by [@&#8203;devin-ai-integration](https://github.com/devin-ai-integration)\[bot] in [#&#8203;43662](BerriAI/litellm#43662)
- fix(proxy): backport [#&#8203;43962](BerriAI/litellm#43962) to stable/1.103.x by [@&#8203;yuneng-berri](https://github.com/yuneng-berri) in [#&#8203;43984](BerriAI/litellm#43984)

**Full Changelog**: <BerriAI/litellm@v1.103.1...v1.103.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 this update 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:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMTUuMTMiLCJ1cGRhdGVkSW5WZXIiOiI0NC4xMTUuMTMiLCJ0YXJnZXRCcmFuY2giOiJtYWluIiwibGFiZWxzIjpbInJlbm92YXRlL2NvbnRhaW5lciIsInR5cGUvcGF0Y2giXX0=-->

Reviewed-on: https://git.greyrock.io/todd/home-ops/pulls/328
yuneng-berri added a commit that referenced this pull request Oct 2, 2026
…th (#44267)

The failure spend-log row from #42695 is written for pass-through routes that
run as LLM API routes, which a config route only does with auth: true. The
test omitted auth and passed only while config wins (#41779) registered config
entries through the typed model, where auth defaults to true. #43962 restored
the pre-config-wins registration, so the route lost that status and the row
was never written. Set auth: true on the route so the test covers the logging
it was written for without depending on that side effect

(cherry picked from commit 1d9cd9b)
yuneng-berri added a commit that referenced this pull request Oct 2, 2026
…th (#44269)

The failure spend-log row from #42695 is written for pass-through routes that
run as LLM API routes, which a config route only does with auth: true. The
test omitted auth and passed only while config wins (#41779) registered config
entries through the typed model, where auth defaults to true. #43962 restored
the pre-config-wins registration, so the route lost that status and the row
was never written. Set auth: true on the route so the test covers the logging
it was written for without depending on that side effect

(cherry picked from commit 1d9cd9b)
yuneng-berri added a commit that referenced this pull request Oct 2, 2026
…th (#44265)

The failure spend-log row from #42695 is written for pass-through routes that
run as LLM API routes, which a config route only does with auth: true. The
test omitted auth and passed only while config wins (#41779) registered config
entries through the typed model, where auth defaults to true. #43962 restored
the pre-config-wins registration, so the route lost that status and the row
was never written. Set auth: true on the route so the test covers the logging
it was written for without depending on that side effect

This branch is waiting to be deployed

1 waiting deployment
e2e-changed — 2144aef4 Waiting Oct 1, 2026 by yuneng-berri via oauth #2271
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants