litellm/tests/integration/security
yucheng-berri 15eca24fc2
fix(guardrails)!: redact secrets in tool traffic and system prompts (#47122)
* fix(guardrails): redact secrets in tool traffic and Anthropic system

* fix(guardrails): bound tool payload scans and stop nested tool_result recursion

Scan each tool value beside its key instead of an indented dump, read
tool_result content one level deep, keep non-finite tool arguments as
raw text, and give read-only guardrails one fragment per tool payload

* test(guardrails): cover read-only guardrail consumers of tool and system text

* fix(guardrails): keep tool argument parsing, scanning and tests within bounds

Treat tool arguments that decode to a lone surrogate as raw text, decode
JSON-escaped detections back to the leaf value, quote unkeyed leaves
without repeating a parent key per list item, drop cycle tracking that
parsed JSON cannot reach, and use the CI license instead of a fake
license server

* fix(guardrails): scan list items beside a capped parent key

List items keep their parent key in the scanned JSON line, capped to its
last 64 characters, so a credential key over a list is still detected
while a long key over many items no longer multiplies the scan text

* fix(guardrails): cap the scanned key after JSON escaping

A key of control characters escaped to six times its length after the
cap, so every list item's scan line grew with it

* fix(guardrails): collapse whitespace in the scanned key context

Space-heavy keys made every inherited list item scan several times slower
than a short key

* fix(guardrails): build each key's scan context once per payload

Repeating the collapse, escape and cut for every list item made a long key
over many items cost key length times item count

* fix(guardrails): cover Responses tool call items and instructions

Responses carries the same tool call arguments and system prompt as chat
and messages under function_call.arguments, custom_tool_call.input and
instructions, so secrets there reached the provider unscanned

* perf(guardrails): skip rescanning text hide-secrets already found clean

Agents resend their whole conversation on every turn, so each turn
rescanned every earlier tool result. Each guardrail now keeps a bounded
set of digests of scan inputs that held no secret and skips those; text
with a secret is always rescanned and no secret material is kept

* fix(guardrails): size the clean-scan cache for many sessions and replace longest secrets first

4096 digests held about 20 long agent sessions per worker, so interleaved
sessions evicted each other and every resend rescanned its history;
65536 digests (about 10 MB) hold a few hundred. Tool payload secrets are
now replaced longest first after JSON unescaping, so a shorter overlapping
match cannot leave part of a secret behind. The key-context test checks
the work it bounds instead of wall-clock time, which CI could not meet

* fix(guardrails): keep unmasked tool argument text and redact keyword matches cut inside an escape

* fix(guardrails): write a tool visitor's whole payload when it changes more than string values

* fix(guardrails): read message text before tool and system text so a vendor error on the new text cannot skip it

* fix(guardrails): moderate tool and system text in its own call so a long payload cannot hide a flagged message

* fix(guardrails): skip the empty moderation call when only tool or system text is present

* fix(guardrails): scan long multi-line tool strings as their own lines so the scan stays linear

* fix(guardrails): keep the key beside every line of a long multi-line tool string

* fix(guardrails): confine tool-traffic coverage to hide-secrets

Restore iter_message_text to its main behavior, so banned keywords, Azure
Content Safety, IBM detectors and the OpenAI and Google moderation hooks
read exactly what they read on main. Only walk_user_text, which
hide-secrets alone calls, still reaches system, instructions and tool
payloads.

* test(guardrails): stop the tool-traffic integration tests from flaking on a busy host

Use the shared per-case timeout for the rig client, and open a new
connection per call in the worker-kill burst so a pooled keep-alive
socket to the killed worker is never reused.

* test(guardrails): drop the wall-clock check from the deep tool arguments unit test

The integration test test_deeply_nested_tool_arguments_do_not_stall_the_worker
already covers the timing; the unit test keeps the redaction check.

---------

Co-authored-by: yucheng-berri <293926326+yucheng-berri@users.noreply.github.com>
2026-10-27 18:11:03 -07:00
..
_callback_traffic.py test(integration): callback credential canary slots C1-C3 and D5 (#43630) 2026-09-29 10:49:30 -07:00
_canary.py test(integration): sweep proxy logs, metrics, a Datadog intake and the Logs drawer for credential canaries (#43306) 2026-09-29 17:57:28 +00:00
_sinks.py test(integration): give each owned proxy a private database and Redis by default (#47213) 2026-10-18 03:37:41 +00:00
_sweeps.py perf(ci): isolate and shard integration suites (#44146) 2026-10-10 11:15:19 -07:00
test_air_gapped_boot.py test: migrate local_testing SDK and provider tests out of build_and_test (#45760) 2026-10-10 23:14:25 +00:00
test_api_key_secret_reference.py fix(secret_managers)!: resolve oidc/file and oidc/env refs in admin-configured api_key per request (#47341) 2026-10-20 01:43:59 +00:00
test_callback_credentials.py test(integration): callback credential canary slots C1-C3 and D5 (#43630) 2026-09-29 10:49:30 -07:00
test_config_deployment_key.py test(integration): credential canary suite harness (#43300) 2026-09-28 16:12:08 -07:00
test_config_overrides.py test(integration): cover config_utils endpoint contracts (#44737) 2026-10-14 07:00:23 +00:00
test_container_ownership.py test(integration): cover videos_containers endpoint contracts (#44691) 2026-10-14 03:49:01 +00:00
test_datadog_sink.py test(integration): sweep proxy logs, metrics, a Datadog intake and the Logs drawer for credential canaries (#43306) 2026-09-29 17:57:28 +00:00
test_files_batches_access.py test(integration): cover files_batches endpoint contracts (#44703) 2026-10-14 06:57:41 +00:00
test_fine_tuning_managed_ids.py fix(managed_files): send provider file ids when creating a fine-tuning job from managed files (#46552) 2026-10-19 14:40:15 -07:00
test_hide_secrets_tool_compatibility.py fix(guardrails)!: redact secrets in tool traffic and system prompts (#47122) 2026-10-27 18:11:03 -07:00
test_hide_secrets_tool_traffic.py fix(guardrails)!: redact secrets in tool traffic and system prompts (#47122) 2026-10-27 18:11:03 -07:00
test_master_key_not_in_db.py test: migrate proxy security, schema migration and MCP legacy tests (#45937) 2026-10-11 16:17:24 -07:00
test_mcp_slots.py test(integration): credential canary slots for MCP and pass-through credentials (#43308) 2026-09-28 17:10:51 -07:00
test_metrics_text.py test(integration): sweep proxy logs, metrics, a Datadog intake and the Logs drawer for credential canaries (#43306) 2026-09-29 17:57:28 +00:00
test_offline_mode.py feat(proxy): add LITELLM_OFFLINE_MODE, one switch for the fetches LiteLLM makes on its own (#48096) 2026-10-23 16:54:19 -07:00
test_passthrough_slots.py test: move routing, caching and callback tests out of local_testing (#45761) 2026-10-10 09:33:09 -07:00
test_proxy_logs.py test(integration): sweep proxy logs, metrics, a Datadog intake and the Logs drawer for credential canaries (#43306) 2026-09-29 17:57:28 +00:00
test_request_path_slots.py test(integration): request-path credential canary slots D1-D4 (#43307) 2026-09-29 10:52:13 -07:00
test_stored_config_slots.py test(integration): cover guardrails_policies endpoint contracts (#44722) 2026-10-14 04:07:26 +00:00
test_sweep_sensitivity.py feat(ui): source Home What's new from day 0 support blog posts (#46260) 2026-10-13 13:11:59 -07:00