mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-06 08:16:43 +00:00
* fix(agents): redact secret litellm_params fields from all /v1/agents responses Secret-bearing litellm_params fields (aws_secret_access_key, api_key, and similar) are now write-only: list, get, create, update, and patch responses always replace them with a fixed marker, regardless of caller role. Editing an agent no longer requires resending a real credential -- an update that omits a sensitive field, or echoes the marker back, preserves the stored value; a real value still rotates it. * fix(agents): redact secrets nested inside dicts/lists in litellm_params too Greptile found that a secret nested one level down under a non-sensitively-named key, or inside a list of per-provider configs, was neither redacted on read nor restored symmetrically on write (the marker string could get persisted as the real value). Recurse into lists on the read side, and mirror that recursion on the write side so restoration isn't limited to top-level keys. Also fixes a regression the redact rewrite introduced (a plain string leaf like a model name was being misinterpreted as a JSON blob and redacted), and suppresses 3 new test-quality-gate findings on an established repo-wide mocking pattern this PR's new tests also use. * fix(agents): guard list-position credential restore against misassignment Two more real gaps Greptile/veria found in the recursive redact/restore mechanism, verified directly against the exact reported shape (litellm_params.model_list, each entry carrying its own nested litellm_params.api_key/aws_secret_access_key) before fixing: - Positional restoration inside a list could attach one entry's stored credential to a different entry if the list were reordered or resized between GET and PUT/PATCH. Restoration by index now only fires when the incoming and existing entries match on every non-secret field; otherwise the caller's own value is used (never a guessed cross-entry secret). - A subtree collapsed to the flat REDACTED_BY_LITELM marker by the read-side recursion depth cap couldn't be recovered on write (the marker string itself would get persisted). Restore now recognizes that shape and recovers the whole existing subtree. Both covered by regression tests mirroring the exact model_list shape reported, mutation-verified. * fix(agents): simplify list-entry credential restore to positional matching The content-match guard from the previous commit fixed one Greptile finding (cross-entry misassignment on reorder) but introduced a worse one: it also rejected restoration whenever an entry's own non-secret fields changed, which is the common case (rename a model_list entry while leaving its own secret masked) -- silently dropping the stored credential on an ordinary edit. There is no stable per-element identity in a plain dict[str, object] schema, so no rule can satisfy both 'restore whenever the entry itself only had its secret masked' and 'never restore across a reorder' at once. Positional correspondence is what every other part of this restore (and the endpoints' full-replace-on-PUT semantics) already assumes, so drop the content-match gate and rely on it here too: this fixes the common case correctly and accepts cross-entry misassignment on a simultaneous reorder-plus-masked-echo as a known, narrow, documented limitation (not a leak between different agents or tenants, since it only reshuffles one agent's own stored values). Tests updated to pin the accepted trade-off explicitly rather than asserting it away, and to cover the previously broken ordinary-edit case. |
||
|---|---|---|
| .. | ||
| azure_client_usage_test.py | ||
| ban_constant_numbers.py | ||
| ban_copy_deepcopy_kwargs.py | ||
| bedrock_pricing.py | ||
| callback_manager_test.py | ||
| check_data_replace_usage.py | ||
| check_e2e_no_raw_requests.py | ||
| check_endpoint_coverage.py | ||
| check_fastuuid_usage.py | ||
| check_get_model_cost_key_performance.py | ||
| check_guardrail_apply_decorator.py | ||
| check_licenses.py | ||
| check_migrations_no_data_rewrites.py | ||
| check_prisma_binary_cache.py | ||
| check_provider_folders_documented.py | ||
| check_spanattributes_value_usage.py | ||
| check_unsafe_enterprise_import.py | ||
| check_workflow_startup_safety.py | ||
| code_qa_check_tests.py | ||
| enforce_llms_folder_style.py | ||
| ensure_async_clients_test.py | ||
| info_log_check.py | ||
| liccheck.ini | ||
| license_cache.json | ||
| litellm_logging_code_coverage.py | ||
| log.txt | ||
| memory_test.py | ||
| pass_through_code_coverage.py | ||
| prevent_key_leaks_in_exceptions.py | ||
| recursive_detector.py | ||
| router_code_coverage.py | ||
| router_enforce_line_length.py | ||
| test_aio_http_image_conversion.py | ||
| test_ban_set_verbose.py | ||
| test_chat_completion_imports.py | ||
| test_no_hardcoded_secrets.py | ||
| test_proxy_types_import.py | ||
| test_router_strategy_async.py | ||
| user_api_key_auth_code_coverage.py | ||