fix(files): return hook-filtered page from GET /v1/files (LIT-4850) - #35424
Conversation
The list_files endpoint narrowed the managed-files post_call_success_hook return to OpenAIFileObject. For list responses that hook returns an AsyncCursorPage filtered to the caller's own files, so the isinstance guard rejected it and the unfiltered provider response went back to the caller, making per-user file filtering a silent no-op. Widen the guard to also accept AsyncCursorPage so the filtered page is returned. Add a regression asserting the endpoint returns the hook's filtered page and another user's file is absent. Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
|
Greptile SummaryThis PR updates the files-list endpoint to honor a page returned by its post-call hook.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains.
|
| Filename | Overview |
|---|---|
| litellm/proxy/openai_files_endpoints/files_endpoints.py | Broadens the accepted post-call hook response type so the processed files page reaches the client. |
| tests/test_litellm/proxy/openai_files_endpoint/test_files_endpoint.py | Adds a regression test that distinguishes the provider page from the page returned by the hook. |
Reviews (2): Last reviewed commit: "style(files): collapse list_files guard ..." | Re-trigger Greptile
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
bugbot run |
There was a problem hiding this comment.
✅ 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 6ab5ab6. Configure here.
|
Closing this. A live e2e (real proxy + real OpenAI, two non-admin users) showed the per-user filtering leak this targeted is not reachable at HEAD: the managed-files hook filters by mutating |
TLDR
Problem this solves:
How it solves it:
Relevant issues
Fixes #28294
Linear ticket
Resolves LIT-4850
Pre-Submission checklist
Screenshots / Proof of Fix
Verified against a real proxy on
http://localhost:4000running the managed-files hook with Postgres, routing to a live OpenAI account (realapi.openai.comuploads, real managed-file rows), at commit6ab5ab68dd. Two non-admininternal_userusers (user-a,user-b) each uploaded one managed batch file, thenGET /v1/fileswas exercised as each user and as admin, before and after the guard change on the same worktree.Post-fix, per-user filtering is correct:
user-asees only their file,user-bonly theirs, and the admin master key sees both (confirming both files exist provider-side).Honest caveat on the reproduction: reverting the guard to the pre-fix
isinstance(_response, OpenAIFileObject)form and restarting produced the exact same result,user-astill saw only their own file with no leak. At this HEAD the managed-files hook filters by mutatingresponse.datain place and returning the same object, sopost_call_success_hookhands the endpoint back an already-filtered object and the guard's reassignment is redundant. Every filtered response also came back with unifiedlitellm_proxy:...ids rather than raw providerfile-...ids, which further shows the filtered object is what is returned in both variants. So this change is a defensive correctness fix that makes the endpoint honor a hook returning a filteredAsyncCursorPageas a new object (a future hook refactor, or any custom hook that returns rather than mutates); it is behavior-neutral at the current HEAD rather than a live before/after leak fix.Type
Bug Fix
Changes
list_filesruns the managed-filespost_call_success_hook, which for list responses filters to the caller's own files and returns anAsyncCursorPage(enterprise/litellm_enterprise/proxy/hooks/managed_files.py). The endpoint then narrowed the hook return withisinstance(_response, OpenAIFileObject), so a filteredAsyncCursorPagereturned as a distinct object would be dropped. The guard now also acceptsAsyncCursorPage, matching the list-filtering return type and the parallel handling increate_file(which stays narrow on purpose since its hook branch returns a singleOpenAIFileObject).As the QA above documents, the shipped hook filters by in-place mutation today, so this is a defensive change rather than a fix for an observable runtime leak.
QA runbook
gpt-4ocurl -s http://localhost:4000/v1/files -H "Authorization: Bearer $KEY" -F purpose=batch -F target_model_names=gpt-4o -F file=@f.jsonlFinal Attestation