litellm/tests/unit/proxy/guardrails
Yogeshwaran Ravichandran 8d9ddb349e
feat(guardrails): add prebuilt credential patterns for OpenAI, Anthropic, and Gemini (#50268)
* feat(guardrails): add prebuilt credential patterns for JWT, and OpenAI, Anthropic, Gemini API keys

* fix(guardrails): prevent quadratic backtracking in jwt_token pattern

* test(guardrails): move credential pattern tests into test_patterns.py

* feat(guardrails): remove jwt_token to keep credential patterns strictly bounded

* fix(guardrails): mask whole provider keys and keep openai_api_key to OpenAI's key shapes

End each pattern so a key ending in "-" is masked in full, require OpenAI's
T3BlbkFJ marker on bare sk- keys so other vendors' sk- keys and LiteLLM
virtual keys are left alone, add sk-None- user keys, and replace the
registration-only tests with whole-match, length-boundary, and negative cases

* fix(guardrails): require the T3BlbkFJ marker on every OpenAI key form and match keys after escaped separators

openai_api_key now needs the marker on the sk-proj-, sk-svcacct-, sk-admin- and sk-None- forms too, as gitleaks and TruffleHog do. anthropic_api_key and gemini_api_key also start a match right after a literal \n or \t or a percent-encoded byte, so keys in pasted JSON strings and URL-encoded logs are masked.

* fix(guardrails): bound the OpenAI key regex, match Gemini prefixes case-sensitively, and hold back long keys in streamed replies

* fix(guardrails): size the streaming holdback per pattern, stop OpenAI key tails before the next key, and allow non-ASCII text after a key

* fix(guardrails): mask content filter pattern matches found in the original text so overlapping patterns cannot split a key

* fix(guardrails): let a block pattern see the text after earlier masking patterns, as before

Masking patterns still match the original text and merge overlapping matches into one tag, but a BLOCK pattern checks the text with the masking patterns listed before it applied, so a request main masked and passed is not blocked now. Detections name only the patterns whose tag was written.

* fix(guardrails): keep content filter masks in order and hold back the longest OpenAI key

Masking patterns run in configured order on the masked text as on main, so a contextual
pattern still matches next to an earlier tag, and each also matches the original text so an
earlier tag cannot split a key. Detections follow the configured pattern, not its name, and
the OpenAI streaming holdback covers the pattern's 419-character longest match.

---------

Co-authored-by: mateo-berri <277851410+mateo-berri@users.noreply.github.com>
2026-11-07 12:29:12 -08:00
..
guardrail_hooks feat(guardrails): add prebuilt credential patterns for OpenAI, Anthropic, and Gemini (#50268) 2026-11-07 12:29:12 -08:00
__init__.py feat(guardrails): send a configured gateway_name from noma_v2 to Noma (#43678) 2026-09-29 10:20:40 -07:00
test_anthropic_sse.py fix(guardrails)!: keep the upstream error when a /v1/messages stream ends in one (#49088) 2026-10-31 02:56:20 -07:00
test_auto_router_compression.py refactor(router): move router callers onto the entry points and invert the proxy imports (#48847) 2026-10-29 17:26:33 +00:00
test_content_filter_path_traversal.py test(proxy): move management_endpoints, management_helpers and guardrails tests into tests/unit/proxy (#44003) 2026-10-01 10:52:03 -07:00
test_content_utils.py fix(guardrails): skip embeddings input in google_text_moderation (#48934) 2026-10-28 20:05:03 -07:00
test_custom_code_security.py test(proxy): move management_endpoints, management_helpers and guardrails tests into tests/unit/proxy (#44003) 2026-10-01 10:52:03 -07:00
test_deferred_guardrail_logging.py refactor(router): route the router family through RoutingContext and close the outside surface (#49118) 2026-10-30 19:18:54 -07:00
test_guardrail_coverage.py fix(guardrails)!: make lakera_v2 on_flagged block reject PII-only detections, add mask (#48944) 2026-10-29 11:48:37 -07:00
test_guardrail_endpoints.py Return configured guardrail native findings (#49217) (#49460) 2026-10-31 23:37:45 +00:00
test_guardrail_initializers.py refactor(types): replace Any with proven types in 157 files (#44798) 2026-10-06 15:31:54 +00:00
test_guardrail_load_balancing.py test: migrate SDK and proxy-booting legacy CircleCI tests to their tiers (#45758) 2026-10-11 00:17:21 -07:00
test_guardrail_registry.py feat(guardrails): split logging_only_scope direction from input-failure policy (#45709) 2026-10-10 01:46:39 -07:00
test_init_guardrails.py fix(config): treat blank env values as unset so the proxy neither crash-loops nor silently drops a guardrail (#46341) 2026-10-14 12:49:31 -07:00
test_llm_as_a_judge.py test(proxy): move management_endpoints, management_helpers and guardrails tests into tests/unit/proxy (#44003) 2026-10-01 10:52:03 -07:00
test_mcp_jwt_signer.py test(proxy): move management_endpoints, management_helpers and guardrails tests into tests/unit/proxy (#44003) 2026-10-01 10:52:03 -07:00
test_pillar_guardrails.py refactor(typing): clear about 1,100 basedpyright Any errors across 303 files (#49986) 2026-11-06 13:31:15 -08:00
test_prompt_security_guardrails.py fix(anthropic)!: send /v1/messages PDF documents to OpenAI-shaped providers as file parts (#47166) 2026-10-29 08:06:12 -07:00
test_qostodian_nexus_guardrail.py test(proxy): move management_endpoints, management_helpers and guardrails tests into tests/unit/proxy (#44003) 2026-10-01 10:52:03 -07:00
test_usage_endpoints.py test(proxy): move management_endpoints, management_helpers and guardrails tests into tests/unit/proxy (#44003) 2026-10-01 10:52:03 -07:00
test_usage_tracking.py feat(accounting): add opt-in SpendLogs ledger (#49856) 2026-11-04 17:49:15 -08:00