mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-07 08:26:10 +00:00
fix(file_search): escape the dropped vector_store_id in the warning
Format the model-picked id with %r so control characters in it cannot break the log line. The regression test for the unlisted id keeps to generic scoping wording
This commit is contained in:
parent
55a6132b31
commit
8bf03c10fd
2 changed files with 8 additions and 12 deletions
|
|
@ -461,7 +461,7 @@ async def _execute_file_search_tool_calls(
|
|||
vs_id_arg = args.get("vector_store_id")
|
||||
if vs_id_arg is not None and vs_id_arg not in all_vs_ids:
|
||||
verbose_logger.warning(
|
||||
"file_search emulated: model picked vector_store_id='%s' outside the request's vector_store_ids %s; "
|
||||
"file_search emulated: model picked vector_store_id=%r outside the request's vector_store_ids %s; "
|
||||
"searching the request's stores instead",
|
||||
vs_id_arg,
|
||||
all_vs_ids,
|
||||
|
|
|
|||
|
|
@ -940,10 +940,8 @@ class TestEmulatedFileSearchHandler:
|
|||
|
||||
@pytest.mark.asyncio
|
||||
async def test_H16_model_chosen_id_outside_request_is_not_searched(self, caplog):
|
||||
"""Security regression: a vector_store_id the model returns that was not in the
|
||||
request's file_search tool must never be searched. Per-key authorization only sees
|
||||
request ids, so honoring an off-schema id leaks stores the key cannot access.
|
||||
The handler must fall back to the request's own stores instead."""
|
||||
"""A vector_store_id the model returns that the request did not list is never
|
||||
searched; the request's own stores are searched instead, with a warning."""
|
||||
from litellm.responses.file_search.emulated_handler import (
|
||||
aresponses_with_emulated_file_search,
|
||||
)
|
||||
|
|
@ -953,11 +951,11 @@ class TestEmulatedFileSearchHandler:
|
|||
{
|
||||
"type": "function_call",
|
||||
"name": "litellm_file_search",
|
||||
"call_id": "call_leak",
|
||||
"arguments": '{"queries": ["launch codeword"], "vector_store_id": "vs_unauthorized"}',
|
||||
"call_id": "call_unlisted",
|
||||
"arguments": '{"queries": ["launch codeword"], "vector_store_id": "vs_unlisted"}',
|
||||
}
|
||||
]
|
||||
first_resp.id = "resp_leak"
|
||||
first_resp.id = "resp_unlisted"
|
||||
first_resp.created_at = 1700000000
|
||||
first_resp.model = "claude-3-5-sonnet"
|
||||
first_resp.usage = None
|
||||
|
|
@ -990,11 +988,9 @@ class TestEmulatedFileSearchHandler:
|
|||
|
||||
searched_ids = [c.kwargs["vector_store_id"] for c in mock_asearch.call_args_list]
|
||||
assert searched_ids, "Expected the vector store to be searched at least once"
|
||||
assert "vs_unauthorized" not in searched_ids, (
|
||||
"Handler searched the off-schema store the model picked; per-key auth never saw it"
|
||||
)
|
||||
assert "vs_unlisted" not in searched_ids, "Handler searched a store the request did not list"
|
||||
assert set(searched_ids) == {"vs_allowed"}
|
||||
dropped_id_warnings = [r for r in caplog.records if "vs_unauthorized" in r.getMessage()]
|
||||
dropped_id_warnings = [r for r in caplog.records if "vs_unlisted" in r.getMessage()]
|
||||
assert len(dropped_id_warnings) == 1, "Expected one warning naming the dropped model-picked id"
|
||||
assert dropped_id_warnings[0].levelno == logging.WARNING
|
||||
assert "vs_allowed" in dropped_id_warnings[0].getMessage()
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue