fix(proxy): allow internal roles to access vector store CRUD routes#30503
Conversation
Add bare /v1/vector_stores/{vector_store_id} to openai_routes so retrieve, update, and delete classify as LLM API routes for internal user and internal viewer roles.
Co-authored-by: Cursor <cursoragent@cursor.com>
Greptile SummaryThis PR fixes a 403 for internal roles (
Confidence Score: 5/5Safe to merge — the change is additive (two new list entries) and cannot revoke access that previously worked. The fix is a two-line addition to a string list; the matching logic ( The test file has a minor coverage gap in
|
| Filename | Overview |
|---|---|
| litellm/proxy/_types.py | Adds /vector_stores/{vector_store_id} and /v1/vector_stores/{vector_store_id} to openai_routes, filling the gap that caused 403s for internal roles on retrieve/update/delete. |
| tests/test_litellm/proxy/auth/test_route_checks.py | Adds two new test functions covering route classification and internal-role access for GET/POST/DELETE on the bare vector store path; the CRUD parametrize only tests the /v1/ prefix, leaving the non-prefixed form untested at that level. |
Reviews (1): Last reviewed commit: "fix(proxy): allow internal roles to acce..." | Re-trigger Greptile
| "method, route", | ||
| [ | ||
| ("GET", "/v1/vector_stores/vs_123"), | ||
| ("POST", "/v1/vector_stores/vs_123"), | ||
| ("DELETE", "/v1/vector_stores/vs_123"), | ||
| ], | ||
| ) |
There was a problem hiding this comment.
The CRUD parametrize only exercises the
/v1/ prefix, but the fix adds both /vector_stores/{vector_store_id} and /v1/vector_stores/{vector_store_id}. A regression in the non-prefixed form would pass test_vector_store_routes_are_llm_api_routes (which covers both at classification level) but the non_proxy_admin_allowed_routes_check path would go unchecked. Adding "/vector_stores/vs_123" to the method, route parametrize closes the gap.
| "method, route", | |
| [ | |
| ("GET", "/v1/vector_stores/vs_123"), | |
| ("POST", "/v1/vector_stores/vs_123"), | |
| ("DELETE", "/v1/vector_stores/vs_123"), | |
| ], | |
| ) | |
| "method, route", | |
| [ | |
| ("GET", "/v1/vector_stores/vs_123"), | |
| ("POST", "/v1/vector_stores/vs_123"), | |
| ("DELETE", "/v1/vector_stores/vs_123"), | |
| ("GET", "/vector_stores/vs_123"), | |
| ("POST", "/vector_stores/vs_123"), | |
| ("DELETE", "/vector_stores/vs_123"), | |
| ], | |
| ) |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
| "/vector_stores", | ||
| "/v1/vector_stores", | ||
| "/vector_stores/{vector_store_id}", | ||
| "/v1/vector_stores/{vector_store_id}", |
There was a problem hiding this comment.
Medium: View-only vector store mutation
Adding the item route to openai_routes makes RouteChecks.non_proxy_admin_allowed_routes_check allow it for INTERNAL_USER_VIEW_ONLY before the view-only role branch runs. A user with that role can call POST or DELETE /v1/vector_stores/{vector_store_id} and update or delete an accessible vector store; keep the route gate method-aware so viewers only get GET access, while write methods require a non-viewer role or explicit write permission.
PR overviewThis pull request updates proxy route authorization so internal roles can access OpenAI-compatible vector store CRUD routes. The touched proxy route definitions affect access handling for There is still an open authorization issue where a view-only internal user may be allowed to perform write operations against an accessible vector store. That creates a limited but concrete integrity and availability risk, since such a user could update or delete vector store data they should only be able to read. No issues have been addressed yet, so the PR still needs a method-aware route check before it is security-ready. Open issues (1)
Fixed/addressed: 0 · PR risk: 6/10 |
902122a
into
litellm_internal_staging
…erriAI#30503) Add bare /v1/vector_stores/{vector_store_id} to openai_routes so retrieve, update, and delete classify as LLM API routes for internal user and internal viewer roles. Co-authored-by: Cursor <cursoragent@cursor.com>
….2) (#327) 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.89.1` → `v1.89.2` | --- ### Release Notes <details> <summary>BerriAI/litellm (ghcr.io/berriai/litellm)</summary> ### [`v1.89.2`](https://github.com/BerriAI/litellm/releases/tag/v1.89.2) [Compare Source](BerriAI/litellm@v1.89.2...v1.89.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.89.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.89.2/cosign.pub \ ghcr.io/berriai/litellm:v1.89.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(ui): rebuild ui by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​30703](BerriAI/litellm#30703) - chore(release): backport [#​30380](BerriAI/litellm#30380), [#​30503](BerriAI/litellm#30503), [#​30558](BerriAI/litellm#30558), [#​30130](BerriAI/litellm#30130), [#​30588](BerriAI/litellm#30588), [#​30495](BerriAI/litellm#30495), [#​30690](BerriAI/litellm#30690) to stable/1.89.x and cut 1.89.2 by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​30681](BerriAI/litellm#30681) **Full Changelog**: <BerriAI/litellm@v1.89.1...v1.89.2> ### [`v1.89.2`](https://github.com/BerriAI/litellm/releases/tag/v1.89.2) [Compare Source](BerriAI/litellm@v1.89.1...v1.89.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.89.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.89.2/cosign.pub \ ghcr.io/berriai/litellm:v1.89.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(ui): rebuild ui by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​30703](BerriAI/litellm#30703) - chore(release): backport [#​30380](BerriAI/litellm#30380), [#​30503](BerriAI/litellm#30503), [#​30558](BerriAI/litellm#30558), [#​30130](BerriAI/litellm#30130), [#​30588](BerriAI/litellm#30588), [#​30495](BerriAI/litellm#30495), [#​30690](BerriAI/litellm#30690) to stable/1.89.x and cut 1.89.2 by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​30681](BerriAI/litellm#30681) **Full Changelog**: <BerriAI/litellm@v1.89.1...v1.89.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](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yMjQuMCIsInVwZGF0ZWRJblZlciI6IjQzLjIyNC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJyZW5vdmF0ZS9jb250YWluZXIiLCJ0eXBlL3BhdGNoIl19--> Reviewed-on: https://git.greyrock.io/greyrock-labs/home-ops/pulls/327
…to v1.89.2 (#206) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [https://github.com/BerriAI/litellm.git](https://github.com/BerriAI/litellm) | patch | `v1.89.1` → `v1.89.2` | --- ### Release Notes <details> <summary>BerriAI/litellm (https://github.com/BerriAI/litellm.git)</summary> ### [`v1.89.2`](https://github.com/BerriAI/litellm/releases/tag/v1.89.2) [Compare Source](BerriAI/litellm@v1.89.1...v1.89.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.89.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.89.2/cosign.pub \ ghcr.io/berriai/litellm:v1.89.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(ui): rebuild ui by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​30703](BerriAI/litellm#30703) - chore(release): backport [#​30380](BerriAI/litellm#30380), [#​30503](BerriAI/litellm#30503), [#​30558](BerriAI/litellm#30558), [#​30130](BerriAI/litellm#30130), [#​30588](BerriAI/litellm#30588), [#​30495](BerriAI/litellm#30495), [#​30690](BerriAI/litellm#30690) to stable/1.89.x and cut 1.89.2 by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​30681](BerriAI/litellm#30681) **Full Changelog**: <BerriAI/litellm@v1.89.1...v1.89.2> </details> --- ### Configuration 📅 **Schedule**: (UTC) - 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](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yMjAuMCIsInVwZGF0ZWRJblZlciI6IjQzLjIyMC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=--> Co-authored-by: Renovate Bot <renovate@bhamm-lab.com> Reviewed-on: https://codeberg.org/blake-hamm/bhamm-lab/pulls/206
….2) (#143) 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.89.1` → `v1.89.2` | --- ### Release Notes <details> <summary>BerriAI/litellm (ghcr.io/berriai/litellm)</summary> ### [`v1.89.2`](https://github.com/BerriAI/litellm/releases/tag/v1.89.2) [Compare Source](BerriAI/litellm@v1.89.2...v1.89.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.89.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.89.2/cosign.pub \ ghcr.io/berriai/litellm:v1.89.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(ui): rebuild ui by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​30703](BerriAI/litellm#30703) - chore(release): backport [#​30380](BerriAI/litellm#30380), [#​30503](BerriAI/litellm#30503), [#​30558](BerriAI/litellm#30558), [#​30130](BerriAI/litellm#30130), [#​30588](BerriAI/litellm#30588), [#​30495](BerriAI/litellm#30495), [#​30690](BerriAI/litellm#30690) to stable/1.89.x and cut 1.89.2 by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​30681](BerriAI/litellm#30681) **Full Changelog**: <BerriAI/litellm@v1.89.1...v1.89.2> ### [`v1.89.2`](https://github.com/BerriAI/litellm/releases/tag/v1.89.2) [Compare Source](BerriAI/litellm@v1.89.1...v1.89.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.89.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.89.2/cosign.pub \ ghcr.io/berriai/litellm:v1.89.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(ui): rebuild ui by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​30703](BerriAI/litellm#30703) - chore(release): backport [#​30380](BerriAI/litellm#30380), [#​30503](BerriAI/litellm#30503), [#​30558](BerriAI/litellm#30558), [#​30130](BerriAI/litellm#30130), [#​30588](BerriAI/litellm#30588), [#​30495](BerriAI/litellm#30495), [#​30690](BerriAI/litellm#30690) to stable/1.89.x and cut 1.89.2 by [@​yuneng-berri](https://github.com/yuneng-berri) in [#​30681](BerriAI/litellm#30681) **Full Changelog**: <BerriAI/litellm@v1.89.1...v1.89.2> </details> --- ### Configuration 📅 **Schedule**: (in timezone Europe/London) - 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](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yMzIuMCIsInVwZGF0ZWRJblZlciI6IjQzLjIzMi4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJyZW5vdmF0ZS9jb250YWluZXIiLCJ0eXBlL3BhdGNoIl19--> Reviewed-on: https://forgejo.hayden.moe/hayden/phoebe/pulls/143
…erriAI#30503) Add bare /v1/vector_stores/{vector_store_id} to openai_routes so retrieve, update, and delete classify as LLM API routes for internal user and internal viewer roles. Co-authored-by: Cursor <cursoragent@cursor.com> (cherry picked from commit 902122a)
Description
Internal user and internal viewer keys could call vector store list, create, search, and file endpoints, but GET/POST/DELETE on /v1/vector_stores/{vector_store_id} returned 403 because the bare resource path was missing from openai_routes. This adds that route pattern and regression tests so retrieve, update, and delete pass the LLM API route gate for those roles. Object-level vector store access checks are unchanged.
Cause
LiteLLMRoutes.openai_routes included /v1/vector_stores and sub-routes like /v1/vector_stores/{vector_store_id}/search and .../files, but not /v1/vector_stores/{vector_store_id} itself. RouteChecks.is_llm_api_route() returned False for retrieve/update/delete URLs, so non_proxy_admin_allowed_routes_check() did not treat them as LLM API routes and internal roles hit the admin-only fallback.
Fix
Add /vector_stores/{vector_store_id} and /v1/vector_stores/{vector_store_id} to openai_routes in litellm/proxy/_types.py. Add regression tests in tests/test_litellm/proxy/auth/test_route_checks.py covering route classification and internal user / internal viewer access for GET, POST, and DELETE on the bare path.