From 91fd2b462116410d0b0cdbaec1f54b620d053629 Mon Sep 17 00:00:00 2001 From: Ishaan Jaff Date: Wed, 18 Feb 2026 18:26:24 -0800 Subject: [PATCH] Add aviation and UAE policy templates with tag-based filtering (#21518) * add aviation and UAE regex patterns (PNR, Skywards, Emirates ID, UAE phone, flight number) * add aviation safety topics category yaml * add airline brand protection category yaml * add UAE cultural sensitivity category yaml * add UAE anti-discrimination category yaml * add aviation, UAE, and competitor policy templates + migrate region/type to tags * sync policy_templates_backup.json * add /policy/templates/enrich endpoint for LLM competitor discovery * add enrichPolicyTemplate networking call * add TemplateParameterModal component * handle parameterized templates and LLM enrichment in policies index * replace region/type radio filters with tag sidebar checkboxes --- litellm/policy_templates_backup.json | 1153 ++++++++++++++--- .../litellm_content_filter/patterns.json | 41 + .../airline_brand_protection.yaml | 89 ++ .../aviation_safety_topics.yaml | 120 ++ .../uae_anti_discrimination.yaml | 71 + .../uae_cultural_sensitivity.yaml | 72 + .../management_endpoints/policy_endpoints.py | 136 +- policy_templates.json | 1048 +++++++++++++-- .../src/components/networking.tsx | 33 + .../src/components/policies/index.tsx | 74 +- .../components/policies/policy_templates.tsx | 198 ++- .../policies/template_parameter_modal.tsx | 127 ++ 12 files changed, 2798 insertions(+), 364 deletions(-) create mode 100644 litellm/proxy/guardrails/guardrail_hooks/litellm_content_filter/policy_templates/airline_brand_protection.yaml create mode 100644 litellm/proxy/guardrails/guardrail_hooks/litellm_content_filter/policy_templates/aviation_safety_topics.yaml create mode 100644 litellm/proxy/guardrails/guardrail_hooks/litellm_content_filter/policy_templates/uae_anti_discrimination.yaml create mode 100644 litellm/proxy/guardrails/guardrail_hooks/litellm_content_filter/policy_templates/uae_cultural_sensitivity.yaml create mode 100644 ui/litellm-dashboard/src/components/policies/template_parameter_modal.tsx diff --git a/litellm/policy_templates_backup.json b/litellm/policy_templates_backup.json index ef272ca7749..f27f20187f9 100644 --- a/litellm/policy_templates_backup.json +++ b/litellm/policy_templates_backup.json @@ -3,7 +3,6 @@ "id": "advanced-au-pii-protection", "title": "Advanced PII Protection (Australia)", "description": "Protects Australian-specific identifiers, international employee data, financial information, credentials, protected class information, and industry-specific sensitive data.", - "region": "AU", "icon": "ShieldCheckIcon", "iconColor": "text-purple-500", "iconBg": "bg-purple-50", @@ -71,22 +70,86 @@ "guardrail": "litellm_content_filter", "mode": "pre_call", "patterns": [ - {"pattern_type": "prebuilt", "pattern_name": "us_ssn", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "us_ssn_no_dash", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "passport_us", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "passport_uk", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "passport_germany", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "passport_france", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "passport_netherlands", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "nl_bsn_contextual", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "passport_china", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "passport_india", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "passport_japan", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "passport_canada", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "br_cpf", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "br_cpf_unformatted", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "br_rg", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "br_cnpj", "action": "MASK"} + { + "pattern_type": "prebuilt", + "pattern_name": "us_ssn", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "us_ssn_no_dash", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "passport_us", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "passport_uk", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "passport_germany", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "passport_france", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "passport_netherlands", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "nl_bsn_contextual", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "passport_china", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "passport_india", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "passport_japan", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "passport_canada", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "br_cpf", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "br_cpf_unformatted", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "br_rg", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "br_cnpj", + "action": "MASK" + } ], "pattern_redaction_format": "[{pattern_name}_REDACTED]" }, @@ -100,12 +163,36 @@ "guardrail": "litellm_content_filter", "mode": "pre_call", "patterns": [ - {"pattern_type": "prebuilt", "pattern_name": "email", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "us_phone", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "br_phone_landline", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "br_phone_mobile", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "street_address", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "br_cep", "action": "MASK"} + { + "pattern_type": "prebuilt", + "pattern_name": "email", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "us_phone", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "br_phone_landline", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "br_phone_mobile", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "street_address", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "br_cep", + "action": "MASK" + } ], "pattern_redaction_format": "[{pattern_name}_REDACTED]" }, @@ -119,12 +206,36 @@ "guardrail": "litellm_content_filter", "mode": "pre_call", "patterns": [ - {"pattern_type": "prebuilt", "pattern_name": "visa", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "mastercard", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "amex", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "discover", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "credit_card", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "iban", "action": "MASK"} + { + "pattern_type": "prebuilt", + "pattern_name": "visa", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "mastercard", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "amex", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "discover", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "credit_card", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "iban", + "action": "MASK" + } ], "pattern_redaction_format": "[{pattern_name}_REDACTED]" }, @@ -138,11 +249,31 @@ "guardrail": "litellm_content_filter", "mode": "pre_call", "patterns": [ - {"pattern_type": "prebuilt", "pattern_name": "aws_access_key", "action": "BLOCK"}, - {"pattern_type": "prebuilt", "pattern_name": "aws_secret_key", "action": "BLOCK"}, - {"pattern_type": "prebuilt", "pattern_name": "github_token", "action": "BLOCK"}, - {"pattern_type": "prebuilt", "pattern_name": "slack_token", "action": "BLOCK"}, - {"pattern_type": "prebuilt", "pattern_name": "generic_api_key", "action": "BLOCK"} + { + "pattern_type": "prebuilt", + "pattern_name": "aws_access_key", + "action": "BLOCK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "aws_secret_key", + "action": "BLOCK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "github_token", + "action": "BLOCK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "slack_token", + "action": "BLOCK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "generic_api_key", + "action": "BLOCK" + } ], "pattern_redaction_format": "[{pattern_name}_REDACTED]" }, @@ -156,8 +287,16 @@ "guardrail": "litellm_content_filter", "mode": "pre_call", "patterns": [ - {"pattern_type": "prebuilt", "pattern_name": "ipv4", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "ipv6", "action": "MASK"} + { + "pattern_type": "prebuilt", + "pattern_name": "ipv4", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "ipv6", + "action": "MASK" + } ], "pattern_redaction_format": "[INTERNAL_IP_REDACTED]" }, @@ -171,14 +310,46 @@ "guardrail": "litellm_content_filter", "mode": "pre_call", "patterns": [ - {"pattern_type": "prebuilt", "pattern_name": "gender_sexual_orientation", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "race_ethnicity_national_origin", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "religion", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "age_discrimination", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "disability", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "marital_family_status", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "military_status", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "public_assistance", "action": "MASK"} + { + "pattern_type": "prebuilt", + "pattern_name": "gender_sexual_orientation", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "race_ethnicity_national_origin", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "religion", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "age_discrimination", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "disability", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "marital_family_status", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "military_status", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "public_assistance", + "action": "MASK" + } ], "pattern_redaction_format": "[PROTECTED_CLASS_INFO_REDACTED]" }, @@ -201,13 +372,16 @@ "protected-class-information" ], "guardrails_remove": [] - } + }, + "tags": [ + "PII Protection", + "Australia" + ] }, { "id": "baseline-pii-protection", "title": "Baseline PII Protection", "description": "Baseline PII protection for internal tools and testing. Focuses on credentials and high-risk identifiers only. Suitable for non-sensitive internal use.", - "region": "Global", "icon": "ShieldCheckIcon", "iconColor": "text-blue-500", "iconBg": "bg-blue-50", @@ -224,13 +398,27 @@ "guardrail": "litellm_content_filter", "mode": "pre_call", "patterns": [ - {"pattern_type": "prebuilt", "pattern_name": "au_tfn", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "au_abn", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "au_medicare", "action": "MASK"} + { + "pattern_type": "prebuilt", + "pattern_name": "au_tfn", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "au_abn", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "au_medicare", + "action": "MASK" + } ], "pattern_redaction_format": "[{pattern_name}_REDACTED]" }, - "guardrail_info": {"description": "Masks Australian Tax File Numbers, Business Numbers, and Medicare Numbers"} + "guardrail_info": { + "description": "Masks Australian Tax File Numbers, Business Numbers, and Medicare Numbers" + } }, { "guardrail_name": "credentials-api-keys", @@ -238,15 +426,37 @@ "guardrail": "litellm_content_filter", "mode": "pre_call", "patterns": [ - {"pattern_type": "prebuilt", "pattern_name": "aws_access_key", "action": "BLOCK"}, - {"pattern_type": "prebuilt", "pattern_name": "aws_secret_key", "action": "BLOCK"}, - {"pattern_type": "prebuilt", "pattern_name": "github_token", "action": "BLOCK"}, - {"pattern_type": "prebuilt", "pattern_name": "slack_token", "action": "BLOCK"}, - {"pattern_type": "prebuilt", "pattern_name": "generic_api_key", "action": "BLOCK"} + { + "pattern_type": "prebuilt", + "pattern_name": "aws_access_key", + "action": "BLOCK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "aws_secret_key", + "action": "BLOCK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "github_token", + "action": "BLOCK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "slack_token", + "action": "BLOCK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "generic_api_key", + "action": "BLOCK" + } ], "pattern_redaction_format": "[{pattern_name}_REDACTED]" }, - "guardrail_info": {"description": "Blocks requests containing API keys and credentials (AWS, GitHub, Slack)"} + "guardrail_info": { + "description": "Blocks requests containing API keys and credentials (AWS, GitHub, Slack)" + } }, { "guardrail_name": "financial-pii", @@ -254,16 +464,42 @@ "guardrail": "litellm_content_filter", "mode": "pre_call", "patterns": [ - {"pattern_type": "prebuilt", "pattern_name": "visa", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "mastercard", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "amex", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "discover", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "credit_card", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "iban", "action": "MASK"} + { + "pattern_type": "prebuilt", + "pattern_name": "visa", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "mastercard", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "amex", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "discover", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "credit_card", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "iban", + "action": "MASK" + } ], "pattern_redaction_format": "[{pattern_name}_REDACTED]" }, - "guardrail_info": {"description": "Masks financial information including credit cards and bank account numbers"} + "guardrail_info": { + "description": "Masks financial information including credit cards and bank account numbers" + } } ], "templateData": { @@ -275,13 +511,15 @@ "financial-pii" ], "guardrails_remove": [] - } + }, + "tags": [ + "PII Protection" + ] }, { "id": "nsfw-content-filter-australia", "title": "NSFW Content Filter (Australia)", "description": "Blocks profanity, sexual content, NSFW requests, self-harm content, and child safety violations using English and Australian-specific slang. Protects against inappropriate content including sexual solicitation, explicit content, Australian profanity, self-harm, and content involving minors.", - "region": "AU", "icon": "ShieldExclamationIcon", "iconColor": "text-red-500", "iconBg": "bg-red-50", @@ -396,13 +634,16 @@ "nsfw-racial-bias-filter" ], "guardrails_remove": [] - } + }, + "tags": [ + "Content Safety", + "Australia" + ] }, { "id": "nsfw-content-filter-basic", "title": "NSFW Content Filter (Basic)", "description": "Basic NSFW content filtering for English only. Blocks profanity, sexual content, slurs, solicitation, explicit requests, self-harm content, and child safety violations. Suitable for most applications requiring content moderation.", - "region": "Global", "icon": "ShieldExclamationIcon", "iconColor": "text-orange-500", "iconBg": "bg-orange-50", @@ -497,13 +738,15 @@ "nsfw-racial-bias-filter-basic" ], "guardrails_remove": [] - } + }, + "tags": [ + "Content Safety" + ] }, { "id": "nsfw-content-filter-all-regions", "title": "NSFW Content Filter (All Regions)", "description": "Comprehensive multi-language NSFW content filtering. Blocks profanity, sexual content, inappropriate requests, self-harm content, and child safety violations in English, Spanish, French, German, and Australian. Best for global applications.", - "region": "Global", "icon": "ShieldExclamationIcon", "iconColor": "text-purple-500", "iconBg": "bg-purple-50", @@ -678,13 +921,15 @@ "nsfw-racial-bias-filter-global" ], "guardrails_remove": [] - } + }, + "tags": [ + "Content Safety" + ] }, { "id": "gdpr-eu-pii-protection", - "title": "GDPR Art. 32 — EU PII Protection", + "title": "GDPR Art. 32 \u2014 EU PII Protection", "description": "GDPR Article 32 compliance for EU personal data protection. Masks French national IDs (NIR/INSEE), EU IBANs, French phone numbers, EU VAT numbers, EU passport numbers, and email addresses. Suitable for applications processing EU citizen data requiring GDPR compliance.", - "region": "EU", "icon": "ShieldCheckIcon", "iconColor": "text-indigo-500", "iconBg": "bg-indigo-50", @@ -702,8 +947,16 @@ "guardrail": "litellm_content_filter", "mode": "pre_call", "patterns": [ - {"pattern_type": "prebuilt", "pattern_name": "fr_nir", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "eu_passport_generic", "action": "MASK"} + { + "pattern_type": "prebuilt", + "pattern_name": "fr_nir", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "eu_passport_generic", + "action": "MASK" + } ], "pattern_redaction_format": "[{pattern_name}_REDACTED]" }, @@ -717,8 +970,16 @@ "guardrail": "litellm_content_filter", "mode": "pre_call", "patterns": [ - {"pattern_type": "prebuilt", "pattern_name": "eu_iban_enhanced", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "iban", "action": "MASK"} + { + "pattern_type": "prebuilt", + "pattern_name": "eu_iban_enhanced", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "iban", + "action": "MASK" + } ], "pattern_redaction_format": "[IBAN_REDACTED]" }, @@ -732,9 +993,21 @@ "guardrail": "litellm_content_filter", "mode": "pre_call", "patterns": [ - {"pattern_type": "prebuilt", "pattern_name": "email", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "fr_phone", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "fr_postal_code", "action": "MASK"} + { + "pattern_type": "prebuilt", + "pattern_name": "email", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "fr_phone", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "fr_postal_code", + "action": "MASK" + } ], "pattern_redaction_format": "[{pattern_name}_REDACTED]" }, @@ -748,7 +1021,11 @@ "guardrail": "litellm_content_filter", "mode": "pre_call", "patterns": [ - {"pattern_type": "prebuilt", "pattern_name": "eu_vat", "action": "MASK"} + { + "pattern_type": "prebuilt", + "pattern_name": "eu_vat", + "action": "MASK" + } ], "pattern_redaction_format": "[VAT_NUMBER_REDACTED]" }, @@ -767,13 +1044,17 @@ "gdpr-eu-business-identifiers" ], "guardrails_remove": [] - } + }, + "tags": [ + "PII Protection", + "Regulatory", + "EU" + ] }, { "id": "eu-ai-act-article5", - "title": "EU AI Act Article 5 — Prohibited Practices", + "title": "EU AI Act Article 5 \u2014 Prohibited Practices", "description": "Comprehensive EU AI Act Article 5 compliance covering all prohibited AI practices. Includes 5 dedicated sub-guardrails per language (English + French) for: subliminal manipulation (Art. 5.1a), vulnerability exploitation (Art. 5.1b), social scoring (Art. 5.1c), emotion recognition in workplace/education (Art. 5.1f), and biometric categorization & predictive profiling (Art. 5.1d/g/h). Uses conditional matching (identifier word + context word).", - "region": "EU", "icon": "ShieldExclamationIcon", "iconColor": "text-red-500", "iconBg": "bg-red-50", @@ -807,7 +1088,7 @@ ] }, "guardrail_info": { - "description": "Art. 5.1(a) — Blocks subliminal manipulation, deceptive AI techniques, dark patterns, and covert behavioral influence" + "description": "Art. 5.1(a) \u2014 Blocks subliminal manipulation, deceptive AI techniques, dark patterns, and covert behavioral influence" } }, { @@ -826,7 +1107,7 @@ ] }, "guardrail_info": { - "description": "Art. 5.1(b) — Blocks AI systems that exploit vulnerabilities of children, elderly, disabled persons, or economically disadvantaged groups" + "description": "Art. 5.1(b) \u2014 Blocks AI systems that exploit vulnerabilities of children, elderly, disabled persons, or economically disadvantaged groups" } }, { @@ -845,7 +1126,7 @@ ] }, "guardrail_info": { - "description": "Art. 5.1(c) — Blocks social credit systems, citizen scoring, trustworthiness classification, and behavioral reputation scoring" + "description": "Art. 5.1(c) \u2014 Blocks social credit systems, citizen scoring, trustworthiness classification, and behavioral reputation scoring" } }, { @@ -864,7 +1145,7 @@ ] }, "guardrail_info": { - "description": "Art. 5.1(f) — Blocks emotion recognition, mood tracking, and sentiment analysis in workplace and educational settings" + "description": "Art. 5.1(f) \u2014 Blocks emotion recognition, mood tracking, and sentiment analysis in workplace and educational settings" } }, { @@ -883,7 +1164,7 @@ ] }, "guardrail_info": { - "description": "Art. 5.1(d)(g)(h) — Blocks biometric categorization by race/ethnicity/religion/politics, facial recognition database scraping, and predictive policing" + "description": "Art. 5.1(d)(g)(h) \u2014 Blocks biometric categorization by race/ethnicity/religion/politics, facial recognition database scraping, and predictive policing" } }, { @@ -902,7 +1183,7 @@ ] }, "guardrail_info": { - "description": "Art. 5.1(a) FR — Bloque la manipulation subliminale, les techniques d'IA trompeuses et les dark patterns (français)" + "description": "Art. 5.1(a) FR \u2014 Bloque la manipulation subliminale, les techniques d'IA trompeuses et les dark patterns (fran\u00e7ais)" } }, { @@ -921,7 +1202,7 @@ ] }, "guardrail_info": { - "description": "Art. 5.1(b) FR — Bloque l'exploitation des vulnérabilités des enfants, personnes âgées et handicapées (français)" + "description": "Art. 5.1(b) FR \u2014 Bloque l'exploitation des vuln\u00e9rabilit\u00e9s des enfants, personnes \u00e2g\u00e9es et handicap\u00e9es (fran\u00e7ais)" } }, { @@ -940,7 +1221,7 @@ ] }, "guardrail_info": { - "description": "Art. 5.1(c) FR — Bloque les systèmes de crédit social, notation des citoyens et classification de fiabilité (français)" + "description": "Art. 5.1(c) FR \u2014 Bloque les syst\u00e8mes de cr\u00e9dit social, notation des citoyens et classification de fiabilit\u00e9 (fran\u00e7ais)" } }, { @@ -959,7 +1240,7 @@ ] }, "guardrail_info": { - "description": "Art. 5.1(f) FR — Bloque la reconnaissance des émotions et l'analyse des sentiments au travail et dans l'éducation (français)" + "description": "Art. 5.1(f) FR \u2014 Bloque la reconnaissance des \u00e9motions et l'analyse des sentiments au travail et dans l'\u00e9ducation (fran\u00e7ais)" } }, { @@ -978,7 +1259,7 @@ ] }, "guardrail_info": { - "description": "Art. 5.1(d)(g)(h) FR — Bloque la catégorisation biométrique, les bases de reconnaissance faciale et le profilage prédictif (français)" + "description": "Art. 5.1(d)(g)(h) FR \u2014 Bloque la cat\u00e9gorisation biom\u00e9trique, les bases de reconnaissance faciale et le profilage pr\u00e9dictif (fran\u00e7ais)" } } ], @@ -998,127 +1279,605 @@ "eu-ai-act-art5-biometric-profiling-fr" ], "guardrails_remove": [] - } + }, + "tags": [ + "Regulatory", + "EU" + ] }, { - "id": "prompt-injection-detection", - "title": "Prompt Injection Detection", - "description": "Detects and blocks prompt injection attacks including SQL injection, malicious code injection, system prompt extraction, jailbreak attempts, and data exfiltration. Applies pre-call screening to block attacks before they reach the LLM.", - "region": "Global", - "icon": "ShieldExclamationIcon", + "id": "mcp-security-unregistered-server-block", + "title": "MCP Security: Block Unregistered Servers", + "description": "Blocks requests that reference MCP servers not registered on this LiteLLM gateway. Prevents unauthorized tool access via unregistered MCP endpoints.", + "icon": "ShieldCheckIcon", "iconColor": "text-red-500", "iconBg": "bg-red-50", "guardrails": [ - "prompt-injection-sql", - "prompt-injection-malicious-code", - "prompt-injection-system-prompt", - "prompt-injection-jailbreak", - "prompt-injection-data-exfiltration" + "mcp-security-block" ], - "complexity": "Medium", + "complexity": "Low", "guardrailDefinitions": [ { - "guardrail_name": "prompt-injection-sql", + "guardrail_name": "mcp-security-block", "litellm_params": { - "guardrail": "litellm_content_filter", + "guardrail": "mcp_security", "mode": "pre_call", - "categories": [ - { - "category": "prompt_injection_sql", - "enabled": true, - "action": "BLOCK", - "severity_threshold": "medium" - } - ] + "default_on": true, + "on_violation": "block" }, "guardrail_info": { - "description": "Blocks SQL injection attempts in prompts (DROP TABLE, UNION SELECT, OR 1=1, etc.)" - } - }, - { - "guardrail_name": "prompt-injection-malicious-code", - "litellm_params": { - "guardrail": "litellm_content_filter", - "mode": "pre_call", - "categories": [ - { - "category": "prompt_injection_malicious_code", - "enabled": true, - "action": "BLOCK", - "severity_threshold": "medium" - } - ] - }, - "guardrail_info": { - "description": "Blocks malicious code injection attempts (shell commands, reverse shells, script injection, encoded payloads)" - } - }, - { - "guardrail_name": "prompt-injection-system-prompt", - "litellm_params": { - "guardrail": "litellm_content_filter", - "mode": "pre_call", - "categories": [ - { - "category": "prompt_injection_system_prompt", - "enabled": true, - "action": "BLOCK", - "severity_threshold": "medium" - } - ] - }, - "guardrail_info": { - "description": "Blocks system prompt extraction and instruction override attempts (ignore previous instructions, reveal your prompt, etc.)" - } - }, - { - "guardrail_name": "prompt-injection-jailbreak", - "litellm_params": { - "guardrail": "litellm_content_filter", - "mode": "pre_call", - "categories": [ - { - "category": "prompt_injection_jailbreak", - "enabled": true, - "action": "BLOCK", - "severity_threshold": "medium" - } - ] - }, - "guardrail_info": { - "description": "Blocks jailbreak attempts (DAN mode, developer mode, safety bypass, token smuggling)" - } - }, - { - "guardrail_name": "prompt-injection-data-exfiltration", - "litellm_params": { - "guardrail": "litellm_content_filter", - "mode": "pre_call", - "categories": [ - { - "category": "prompt_injection_data_exfiltration", - "enabled": true, - "action": "BLOCK", - "severity_threshold": "medium" - } - ] - }, - "guardrail_info": { - "description": "Blocks data exfiltration attempts (extract training data, dump database, steal credentials, etc.)" + "description": "Blocks requests referencing MCP servers not in the gateway registry" } } ], "templateData": { - "policy_name": "prompt-injection-detection", - "description": "Prompt injection detection policy. Blocks SQL injection, malicious code injection, system prompt extraction, jailbreak attempts, and data exfiltration in prompts before they reach the LLM.", + "policy_name": "mcp-security-unregistered-server-block", + "description": "Blocks requests referencing MCP servers not registered on this gateway.", "guardrails_add": [ - "prompt-injection-sql", - "prompt-injection-malicious-code", - "prompt-injection-system-prompt", - "prompt-injection-jailbreak", - "prompt-injection-data-exfiltration" + "mcp-security-block" ], "guardrails_remove": [] - } + }, + "tags": [ + "Security" + ] + }, + { + "id": "airline-passenger-data-protection-uae", + "title": "Airline Passenger Data Protection (UAE)", + "description": "Protects airline passenger PII including PNR/booking references, multi-national passport numbers, frequent flyer (Skywards) numbers, payment cards, IBANs, Emirates ID, UAE phone numbers, and email addresses. Designed for UAE-based airlines operating global routes.", + "icon": "ShieldCheckIcon", + "iconColor": "text-emerald-500", + "iconBg": "bg-emerald-50", + "guardrails": [ + "airline-pnr-skywards-pii", + "airline-passport-multinational", + "airline-payment-financial", + "airline-contact-info-uae" + ], + "complexity": "High", + "guardrailDefinitions": [ + { + "guardrail_name": "airline-pnr-skywards-pii", + "litellm_params": { + "guardrail": "litellm_content_filter", + "mode": "pre_call", + "patterns": [ + { + "pattern_type": "prebuilt", + "pattern_name": "airline_pnr", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "skywards_number", + "action": "MASK" + } + ], + "pattern_redaction_format": "[{pattern_name}_REDACTED]" + }, + "guardrail_info": { + "description": "Masks airline PNR/booking references and Emirates Skywards frequent flyer numbers" + } + }, + { + "guardrail_name": "airline-passport-multinational", + "litellm_params": { + "guardrail": "litellm_content_filter", + "mode": "pre_call", + "patterns": [ + { + "pattern_type": "prebuilt", + "pattern_name": "passport_us", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "passport_uk", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "passport_germany", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "passport_france", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "passport_india", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "passport_china", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "passport_australia", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "passport_japan", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "passport_canada", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "passport_netherlands", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "uae_emirates_id", + "action": "MASK" + } + ], + "pattern_redaction_format": "[{pattern_name}_REDACTED]" + }, + "guardrail_info": { + "description": "Masks passport numbers from 10+ nationalities and UAE Emirates ID -- covers global route network" + } + }, + { + "guardrail_name": "airline-payment-financial", + "litellm_params": { + "guardrail": "litellm_content_filter", + "mode": "pre_call", + "patterns": [ + { + "pattern_type": "prebuilt", + "pattern_name": "credit_card", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "visa", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "mastercard", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "amex", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "iban", + "action": "MASK" + } + ], + "pattern_redaction_format": "[{pattern_name}_REDACTED]" + }, + "guardrail_info": { + "description": "Masks credit card numbers (Visa, Mastercard, Amex) and IBANs" + } + }, + { + "guardrail_name": "airline-contact-info-uae", + "litellm_params": { + "guardrail": "litellm_content_filter", + "mode": "pre_call", + "patterns": [ + { + "pattern_type": "prebuilt", + "pattern_name": "email", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "uae_phone", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "us_phone", + "action": "MASK" + } + ], + "pattern_redaction_format": "[{pattern_name}_REDACTED]" + }, + "guardrail_info": { + "description": "Masks email addresses and phone numbers (UAE and international formats)" + } + } + ], + "templateData": { + "policy_name": "airline-passenger-data-protection-uae", + "description": "Airline passenger data protection for UAE-based carriers. Masks PNR/booking references, Skywards numbers, multi-national passports, Emirates ID, payment cards, IBANs, and contact information.", + "guardrails_add": [ + "airline-pnr-skywards-pii", + "airline-passport-multinational", + "airline-payment-financial", + "airline-contact-info-uae" + ], + "guardrails_remove": [] + }, + "tags": [ + "PII Protection", + "Aviation", + "UAE" + ] + }, + { + "id": "aviation-operations-security", + "title": "Aviation Operations Security", + "description": "Prevents AI from leaking flight operations data (flight numbers, crew schedules, gate assignments, aircraft tail numbers), generating content about aviation security vulnerabilities or bypass procedures, and producing unauthorized airline statements or fake incident reports.", + "icon": "ShieldExclamationIcon", + "iconColor": "text-red-500", + "iconBg": "bg-red-50", + "guardrails": [ + "aviation-ops-data-protection", + "aviation-safety-topic-filter", + "airline-brand-protection-filter" + ], + "complexity": "High", + "parameters": [ + { + "name": "brand_name", + "label": "Your Airline / Brand Name", + "type": "text", + "required": true, + "placeholder": "e.g. Emirates" + } + ], + "guardrailDefinitions": [ + { + "guardrail_name": "aviation-ops-data-protection", + "litellm_params": { + "guardrail": "litellm_content_filter", + "mode": "pre_call", + "patterns": [ + { + "pattern_type": "prebuilt", + "pattern_name": "flight_number", + "action": "MASK" + }, + { + "pattern_type": "regex", + "name": "aircraft_tail_number", + "pattern": "\\bA6-[A-Z]{3}\\b|\\b[A-Z]-[A-Z]{4}\\b|\\bN[0-9]{1,5}[A-Z]{0,2}\\b", + "action": "MASK" + } + ], + "blocked_words": [ + { + "keyword": "crew roster", + "action": "BLOCK", + "description": "Crew scheduling data" + }, + { + "keyword": "crew schedule", + "action": "BLOCK", + "description": "Crew scheduling data" + }, + { + "keyword": "duty roster", + "action": "BLOCK", + "description": "Staff duty data" + }, + { + "keyword": "pilot roster", + "action": "BLOCK", + "description": "Pilot scheduling data" + }, + { + "keyword": "cabin crew list", + "action": "BLOCK", + "description": "Crew manifest data" + } + ], + "pattern_redaction_format": "[{pattern_name}_REDACTED]" + }, + "guardrail_info": { + "description": "Masks flight numbers and aircraft registrations. Blocks crew scheduling and gate assignment data leakage." + } + }, + { + "guardrail_name": "aviation-safety-topic-filter", + "litellm_params": { + "guardrail": "litellm_content_filter", + "mode": "pre_call", + "categories": [ + { + "category": "aviation_safety_topics", + "category_file": "litellm/proxy/guardrails/guardrail_hooks/litellm_content_filter/policy_templates/aviation_safety_topics.yaml", + "enabled": true, + "action": "BLOCK", + "severity_threshold": "medium" + } + ] + }, + "guardrail_info": { + "description": "Blocks content about aircraft vulnerabilities, security bypass procedures, cockpit access, and aviation system exploitation" + } + }, + { + "guardrail_name": "airline-brand-protection-filter", + "litellm_params": { + "guardrail": "litellm_content_filter", + "mode": "post_call", + "categories": [ + { + "category": "airline_brand_protection", + "category_file": "litellm/proxy/guardrails/guardrail_hooks/litellm_content_filter/policy_templates/airline_brand_protection.yaml", + "enabled": true, + "action": "BLOCK", + "severity_threshold": "medium" + } + ], + "blocked_words": [ + { + "keyword": "{{brand_name}} plane crash", + "action": "BLOCK", + "description": "Fake crash report" + }, + { + "keyword": "{{brand_name}} flight crashed", + "action": "BLOCK", + "description": "Fake crash report" + }, + { + "keyword": "{{brand_name}} crash landing", + "action": "BLOCK", + "description": "Fake incident" + }, + { + "keyword": "{{brand_name}} emergency", + "action": "BLOCK", + "description": "Fake emergency" + }, + { + "keyword": "{{brand_name}} passengers dead", + "action": "BLOCK", + "description": "Fake fatality report" + }, + { + "keyword": "{{brand_name}} confirms fatalities", + "action": "BLOCK", + "description": "Fake fatality confirmation" + }, + { + "keyword": "{{brand_name}} safety scandal", + "action": "BLOCK", + "description": "Fake scandal" + }, + { + "keyword": "{{brand_name}} cover up", + "action": "BLOCK", + "description": "Fake coverup claim" + }, + { + "keyword": "{{brand_name}} fleet grounded", + "action": "BLOCK", + "description": "Fake grounding claim" + }, + { + "keyword": "{{brand_name}} discrimination lawsuit", + "action": "BLOCK", + "description": "Fake lawsuit" + } + ] + }, + "guardrail_info": { + "description": "Blocks AI-generated fake incident reports, unauthorized statements, and reputation-damaging content about your brand (runs on output)" + } + } + ], + "templateData": { + "policy_name": "aviation-operations-security", + "description": "Aviation operations security policy. Protects flight ops data, blocks aviation security vulnerability content, and prevents fake airline incident reports and unauthorized statements.", + "guardrails_add": [ + "aviation-ops-data-protection", + "aviation-safety-topic-filter", + "airline-brand-protection-filter" + ], + "guardrails_remove": [] + }, + "tags": [ + "Aviation", + "Security" + ] + }, + { + "id": "uae-regulatory-compliance", + "title": "UAE Regulatory Compliance", + "description": "Compliance with UAE Federal Decree-Law No. 45/2021 (Data Protection) and Federal Decree-Law No. 2/2015 (Anti-Discrimination). Protects Emirates ID numbers, UAE phone numbers, and ensures cultural sensitivity including royal family references and religious content policies.", + "icon": "CheckCircleIcon", + "iconColor": "text-blue-500", + "iconBg": "bg-blue-50", + "guardrails": [ + "uae-data-protection-pii", + "uae-cultural-sensitivity-filter", + "uae-anti-discrimination-filter" + ], + "complexity": "Medium", + "guardrailDefinitions": [ + { + "guardrail_name": "uae-data-protection-pii", + "litellm_params": { + "guardrail": "litellm_content_filter", + "mode": "pre_call", + "patterns": [ + { + "pattern_type": "prebuilt", + "pattern_name": "uae_emirates_id", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "uae_phone", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "email", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "iban", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "credit_card", + "action": "MASK" + }, + { + "pattern_type": "regex", + "name": "uae_po_box", + "pattern": "\\b[Pp]\\.?[Oo]\\.?\\s*[Bb]ox\\s*\\d{1,6}\\b", + "action": "MASK" + } + ], + "pattern_redaction_format": "[{pattern_name}_REDACTED]" + }, + "guardrail_info": { + "description": "UAE Federal Decree-Law No. 45/2021 compliance -- masks Emirates ID, UAE phone numbers, email, IBAN, payment cards, and PO Box addresses" + } + }, + { + "guardrail_name": "uae-cultural-sensitivity-filter", + "litellm_params": { + "guardrail": "litellm_content_filter", + "mode": "pre_call", + "categories": [ + { + "category": "uae_cultural_sensitivity", + "category_file": "litellm/proxy/guardrails/guardrail_hooks/litellm_content_filter/policy_templates/uae_cultural_sensitivity.yaml", + "enabled": true, + "action": "BLOCK", + "severity_threshold": "medium" + } + ] + }, + "guardrail_info": { + "description": "Blocks content disrespecting UAE royal family, cultural norms, and religious sensitivities" + } + }, + { + "guardrail_name": "uae-anti-discrimination-filter", + "litellm_params": { + "guardrail": "litellm_content_filter", + "mode": "pre_call", + "categories": [ + { + "category": "uae_anti_discrimination", + "category_file": "litellm/proxy/guardrails/guardrail_hooks/litellm_content_filter/policy_templates/uae_anti_discrimination.yaml", + "enabled": true, + "action": "BLOCK", + "severity_threshold": "medium" + } + ] + }, + "guardrail_info": { + "description": "UAE Federal Decree-Law No. 2/2015 compliance -- blocks discriminatory content based on race, religion, caste, ethnicity, or nationality" + } + } + ], + "templateData": { + "policy_name": "uae-regulatory-compliance", + "description": "UAE regulatory compliance policy. Covers Federal Decree-Law No. 45/2021 (Data Protection) and Federal Decree-Law No. 2/2015 (Anti-Discrimination). Protects Emirates ID, UAE contact info, and ensures cultural and religious sensitivity.", + "guardrails_add": [ + "uae-data-protection-pii", + "uae-cultural-sensitivity-filter", + "uae-anti-discrimination-filter" + ], + "guardrails_remove": [] + }, + "tags": [ + "Regulatory", + "UAE" + ] + }, + { + "id": "competitor-mention-detection", + "title": "Competitor Mention Detection", + "description": "Automatically detects and blocks AI from recommending or promoting competitor brands. Uses LLM-powered discovery to identify your top competitors, then monitors both inputs and outputs for competitor mentions, referrals, and comparisons that could divert business.", + "icon": "ShieldExclamationIcon", + "iconColor": "text-orange-500", + "iconBg": "bg-orange-50", + "guardrails": [ + "competitor-output-blocker", + "competitor-recommendation-filter", + "competitor-comparison-filter" + ], + "complexity": "Medium", + "parameters": [ + { + "name": "brand_name", + "label": "Your Brand Name", + "type": "text", + "required": true, + "placeholder": "e.g. Emirates" + } + ], + "llm_enrichment": { + "parameter": "brand_name", + "prompt": "List the top 10 direct competitors of {{brand_name}} in the same industry. Return ONLY company/brand names, one per line, no numbering, no explanations.", + "result_key": "competitors" + }, + "guardrailDefinitions": [ + { + "guardrail_name": "competitor-output-blocker", + "litellm_params": { + "guardrail": "litellm_content_filter", + "mode": "post_call", + "blocked_words": "{{competitors_blocked_words}}" + }, + "guardrail_info": { + "description": "Blocks AI outputs that mention or promote competitor brands (auto-discovered via LLM)" + } + }, + { + "guardrail_name": "competitor-recommendation-filter", + "litellm_params": { + "guardrail": "litellm_content_filter", + "mode": "post_call", + "blocked_words": "{{competitor_recommendation_words}}" + }, + "guardrail_info": { + "description": "Blocks AI from recommending, suggesting, or directing users to competitor services" + } + }, + { + "guardrail_name": "competitor-comparison-filter", + "litellm_params": { + "guardrail": "litellm_content_filter", + "mode": "post_call", + "blocked_words": "{{competitor_comparison_words}}" + }, + "guardrail_info": { + "description": "Blocks unfavorable comparisons between your brand and competitors in AI outputs" + } + } + ], + "templateData": { + "policy_name": "competitor-mention-detection", + "description": "Detects and blocks competitor mentions in AI outputs. Uses LLM-powered competitor discovery based on your brand name.", + "guardrails_add": [ + "competitor-output-blocker", + "competitor-recommendation-filter", + "competitor-comparison-filter" + ], + "guardrails_remove": [] + }, + "tags": [ + "Brand Protection" + ] } -] +] \ No newline at end of file diff --git a/litellm/proxy/guardrails/guardrail_hooks/litellm_content_filter/patterns.json b/litellm/proxy/guardrails/guardrail_hooks/litellm_content_filter/patterns.json index 8bb231102a3..88328de09b6 100644 --- a/litellm/proxy/guardrails/guardrail_hooks/litellm_content_filter/patterns.json +++ b/litellm/proxy/guardrails/guardrail_hooks/litellm_content_filter/patterns.json @@ -452,6 +452,47 @@ "pattern": "\\b\\d{1,6}\\s+[A-Za-z0-9][A-Za-z0-9\\s.'-]*\\s+(?:Street|St|Avenue|Ave|Road|Rd|Boulevard|Blvd|Drive|Dr|Lane|Ln|Way|Court|Ct|Place|Pl|Circle|Cir)\\b", "category": "PII Patterns", "description": "Detects street addresses (number + street name + street type)" + }, + { + "name": "airline_pnr", + "display_name": "Airline PNR / Booking Reference", + "pattern": "\\b[A-Z]{6}\\b", + "category": "Aviation PII Patterns", + "description": "Detects airline PNR / booking references (6 uppercase alpha characters) when near booking context", + "keyword_pattern": "\\b(?:PNR|booking\\s*(?:reference|ref|code|number|confirmation)|reservation\\s*(?:code|number|ref)|record\\s*locator|confirmation\\s*(?:code|number)|itinerary\\s*(?:number|ref))\\b", + "allow_word_numbers": false + }, + { + "name": "skywards_number", + "display_name": "Emirates Skywards / Frequent Flyer Number", + "pattern": "\\b(?:EK\\s?)?\\d{9,10}\\b", + "category": "Aviation PII Patterns", + "description": "Detects Emirates Skywards frequent flyer numbers (9-10 digits, optional EK prefix) when near loyalty/frequent flyer context", + "keyword_pattern": "\\b(?:[Ss]kywards|frequent\\s*flyer|FF\\s*(?:number|no|#)|loyalty\\s*(?:number|id|member)|member\\s*(?:number|id|#)|miles\\s*(?:account|number)|tier\\s*(?:number|status))\\b", + "allow_word_numbers": false + }, + { + "name": "uae_emirates_id", + "display_name": "UAE Emirates ID", + "pattern": "\\b784-?\\d{4}-?\\d{7}-?\\d\\b", + "category": "UAE PII Patterns", + "description": "Detects UAE Emirates ID numbers (784-YYYY-NNNNNNN-C format, 15 digits starting with 784)" + }, + { + "name": "uae_phone", + "display_name": "Phone Number (UAE)", + "pattern": "(? dict: + """ + Enrich a policy template with LLM-discovered data (e.g. competitor names). + + Calls an onboarded LLM to discover competitors for the given brand name, + then returns enriched guardrailDefinitions with the discovered data populated. + """ + templates = _load_policy_templates_from_local_backup() + template = next((t for t in templates if t.get("id") == data.template_id), None) + if template is None: + raise HTTPException(status_code=404, detail=f"Template '{data.template_id}' not found") + + llm_enrichment = template.get("llm_enrichment") + if llm_enrichment is None: + raise HTTPException( + status_code=400, + detail="Template does not support LLM enrichment", + ) + + brand_name = data.parameters.get(llm_enrichment["parameter"], "") + if not brand_name: + raise HTTPException( + status_code=400, + detail=f"Parameter '{llm_enrichment['parameter']}' is required", + ) + + prompt = llm_enrichment["prompt"].replace( + "{{" + llm_enrichment["parameter"] + "}}", brand_name + ) + + competitors = await _discover_competitors_via_llm(prompt) + + enriched_definitions = _build_competitor_guardrail_definitions( + template.get("guardrailDefinitions", []), + competitors, + brand_name, + ) + + return {"guardrailDefinitions": enriched_definitions, "competitors": competitors} + + +async def _discover_competitors_via_llm(prompt: str) -> list: + """Call an onboarded LLM to discover competitor names.""" + import litellm + + try: + response = await litellm.acompletion( + model="gpt-4o-mini", + messages=[{"role": "user", "content": prompt}], + temperature=0.3, + ) + raw = response.choices[0].message.content or "" # type: ignore + competitors = [ + line.strip().strip(".-) ").strip() + for line in raw.strip().split("\n") + if line.strip() and len(line.strip()) > 1 + ] + return competitors[:15] + except Exception as e: + verbose_proxy_logger.error("LLM competitor discovery failed: %s", e) + return [] + + +def _build_competitor_guardrail_definitions( + definitions: list, + competitors: list, + brand_name: str, +) -> list: + """Build enriched guardrailDefinitions with competitor names populated.""" + import copy + + enriched = copy.deepcopy(definitions) + + output_blocked = [ + {"keyword": comp, "action": "BLOCK", "description": f"Competitor: {comp}"} + for comp in competitors + ] + + recommendation_blocked = [] + for comp in competitors: + recommendation_blocked.append( + {"keyword": f"try {comp}", "action": "BLOCK", "description": "Recommendation to competitor"} + ) + recommendation_blocked.append( + {"keyword": f"use {comp}", "action": "BLOCK", "description": "Recommendation to competitor"} + ) + recommendation_blocked.append( + {"keyword": f"switch to {comp}", "action": "BLOCK", "description": "Recommendation to competitor"} + ) + recommendation_blocked.append( + {"keyword": f"consider {comp}", "action": "BLOCK", "description": "Recommendation to competitor"} + ) + + comparison_blocked = [] + for comp in competitors: + comparison_blocked.append( + {"keyword": f"{comp} is better", "action": "BLOCK", "description": "Unfavorable comparison"} + ) + comparison_blocked.append( + {"keyword": f"better than {brand_name}", "action": "BLOCK", "description": "Unfavorable comparison"} + ) + comparison_blocked.append( + {"keyword": f"{brand_name} is worse", "action": "BLOCK", "description": "Unfavorable comparison"} + ) + + blocked_words_map = { + "competitor-output-blocker": output_blocked, + "competitor-recommendation-filter": recommendation_blocked, + "competitor-comparison-filter": comparison_blocked, + } + + for defn in enriched: + guardrail_name = defn.get("guardrail_name", "") + if guardrail_name in blocked_words_map: + defn["litellm_params"]["blocked_words"] = blocked_words_map[guardrail_name] + + return enriched diff --git a/policy_templates.json b/policy_templates.json index 5d2e8b72e77..f27f20187f9 100644 --- a/policy_templates.json +++ b/policy_templates.json @@ -3,7 +3,6 @@ "id": "advanced-au-pii-protection", "title": "Advanced PII Protection (Australia)", "description": "Protects Australian-specific identifiers, international employee data, financial information, credentials, protected class information, and industry-specific sensitive data.", - "region": "AU", "icon": "ShieldCheckIcon", "iconColor": "text-purple-500", "iconBg": "bg-purple-50", @@ -71,22 +70,86 @@ "guardrail": "litellm_content_filter", "mode": "pre_call", "patterns": [ - {"pattern_type": "prebuilt", "pattern_name": "us_ssn", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "us_ssn_no_dash", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "passport_us", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "passport_uk", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "passport_germany", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "passport_france", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "passport_netherlands", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "nl_bsn_contextual", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "passport_china", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "passport_india", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "passport_japan", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "passport_canada", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "br_cpf", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "br_cpf_unformatted", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "br_rg", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "br_cnpj", "action": "MASK"} + { + "pattern_type": "prebuilt", + "pattern_name": "us_ssn", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "us_ssn_no_dash", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "passport_us", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "passport_uk", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "passport_germany", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "passport_france", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "passport_netherlands", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "nl_bsn_contextual", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "passport_china", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "passport_india", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "passport_japan", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "passport_canada", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "br_cpf", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "br_cpf_unformatted", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "br_rg", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "br_cnpj", + "action": "MASK" + } ], "pattern_redaction_format": "[{pattern_name}_REDACTED]" }, @@ -100,12 +163,36 @@ "guardrail": "litellm_content_filter", "mode": "pre_call", "patterns": [ - {"pattern_type": "prebuilt", "pattern_name": "email", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "us_phone", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "br_phone_landline", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "br_phone_mobile", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "street_address", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "br_cep", "action": "MASK"} + { + "pattern_type": "prebuilt", + "pattern_name": "email", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "us_phone", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "br_phone_landline", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "br_phone_mobile", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "street_address", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "br_cep", + "action": "MASK" + } ], "pattern_redaction_format": "[{pattern_name}_REDACTED]" }, @@ -119,12 +206,36 @@ "guardrail": "litellm_content_filter", "mode": "pre_call", "patterns": [ - {"pattern_type": "prebuilt", "pattern_name": "visa", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "mastercard", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "amex", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "discover", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "credit_card", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "iban", "action": "MASK"} + { + "pattern_type": "prebuilt", + "pattern_name": "visa", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "mastercard", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "amex", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "discover", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "credit_card", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "iban", + "action": "MASK" + } ], "pattern_redaction_format": "[{pattern_name}_REDACTED]" }, @@ -138,11 +249,31 @@ "guardrail": "litellm_content_filter", "mode": "pre_call", "patterns": [ - {"pattern_type": "prebuilt", "pattern_name": "aws_access_key", "action": "BLOCK"}, - {"pattern_type": "prebuilt", "pattern_name": "aws_secret_key", "action": "BLOCK"}, - {"pattern_type": "prebuilt", "pattern_name": "github_token", "action": "BLOCK"}, - {"pattern_type": "prebuilt", "pattern_name": "slack_token", "action": "BLOCK"}, - {"pattern_type": "prebuilt", "pattern_name": "generic_api_key", "action": "BLOCK"} + { + "pattern_type": "prebuilt", + "pattern_name": "aws_access_key", + "action": "BLOCK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "aws_secret_key", + "action": "BLOCK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "github_token", + "action": "BLOCK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "slack_token", + "action": "BLOCK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "generic_api_key", + "action": "BLOCK" + } ], "pattern_redaction_format": "[{pattern_name}_REDACTED]" }, @@ -156,8 +287,16 @@ "guardrail": "litellm_content_filter", "mode": "pre_call", "patterns": [ - {"pattern_type": "prebuilt", "pattern_name": "ipv4", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "ipv6", "action": "MASK"} + { + "pattern_type": "prebuilt", + "pattern_name": "ipv4", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "ipv6", + "action": "MASK" + } ], "pattern_redaction_format": "[INTERNAL_IP_REDACTED]" }, @@ -171,14 +310,46 @@ "guardrail": "litellm_content_filter", "mode": "pre_call", "patterns": [ - {"pattern_type": "prebuilt", "pattern_name": "gender_sexual_orientation", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "race_ethnicity_national_origin", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "religion", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "age_discrimination", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "disability", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "marital_family_status", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "military_status", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "public_assistance", "action": "MASK"} + { + "pattern_type": "prebuilt", + "pattern_name": "gender_sexual_orientation", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "race_ethnicity_national_origin", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "religion", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "age_discrimination", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "disability", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "marital_family_status", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "military_status", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "public_assistance", + "action": "MASK" + } ], "pattern_redaction_format": "[PROTECTED_CLASS_INFO_REDACTED]" }, @@ -201,13 +372,16 @@ "protected-class-information" ], "guardrails_remove": [] - } + }, + "tags": [ + "PII Protection", + "Australia" + ] }, { "id": "baseline-pii-protection", "title": "Baseline PII Protection", "description": "Baseline PII protection for internal tools and testing. Focuses on credentials and high-risk identifiers only. Suitable for non-sensitive internal use.", - "region": "Global", "icon": "ShieldCheckIcon", "iconColor": "text-blue-500", "iconBg": "bg-blue-50", @@ -224,13 +398,27 @@ "guardrail": "litellm_content_filter", "mode": "pre_call", "patterns": [ - {"pattern_type": "prebuilt", "pattern_name": "au_tfn", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "au_abn", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "au_medicare", "action": "MASK"} + { + "pattern_type": "prebuilt", + "pattern_name": "au_tfn", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "au_abn", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "au_medicare", + "action": "MASK" + } ], "pattern_redaction_format": "[{pattern_name}_REDACTED]" }, - "guardrail_info": {"description": "Masks Australian Tax File Numbers, Business Numbers, and Medicare Numbers"} + "guardrail_info": { + "description": "Masks Australian Tax File Numbers, Business Numbers, and Medicare Numbers" + } }, { "guardrail_name": "credentials-api-keys", @@ -238,15 +426,37 @@ "guardrail": "litellm_content_filter", "mode": "pre_call", "patterns": [ - {"pattern_type": "prebuilt", "pattern_name": "aws_access_key", "action": "BLOCK"}, - {"pattern_type": "prebuilt", "pattern_name": "aws_secret_key", "action": "BLOCK"}, - {"pattern_type": "prebuilt", "pattern_name": "github_token", "action": "BLOCK"}, - {"pattern_type": "prebuilt", "pattern_name": "slack_token", "action": "BLOCK"}, - {"pattern_type": "prebuilt", "pattern_name": "generic_api_key", "action": "BLOCK"} + { + "pattern_type": "prebuilt", + "pattern_name": "aws_access_key", + "action": "BLOCK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "aws_secret_key", + "action": "BLOCK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "github_token", + "action": "BLOCK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "slack_token", + "action": "BLOCK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "generic_api_key", + "action": "BLOCK" + } ], "pattern_redaction_format": "[{pattern_name}_REDACTED]" }, - "guardrail_info": {"description": "Blocks requests containing API keys and credentials (AWS, GitHub, Slack)"} + "guardrail_info": { + "description": "Blocks requests containing API keys and credentials (AWS, GitHub, Slack)" + } }, { "guardrail_name": "financial-pii", @@ -254,16 +464,42 @@ "guardrail": "litellm_content_filter", "mode": "pre_call", "patterns": [ - {"pattern_type": "prebuilt", "pattern_name": "visa", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "mastercard", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "amex", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "discover", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "credit_card", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "iban", "action": "MASK"} + { + "pattern_type": "prebuilt", + "pattern_name": "visa", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "mastercard", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "amex", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "discover", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "credit_card", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "iban", + "action": "MASK" + } ], "pattern_redaction_format": "[{pattern_name}_REDACTED]" }, - "guardrail_info": {"description": "Masks financial information including credit cards and bank account numbers"} + "guardrail_info": { + "description": "Masks financial information including credit cards and bank account numbers" + } } ], "templateData": { @@ -275,13 +511,15 @@ "financial-pii" ], "guardrails_remove": [] - } + }, + "tags": [ + "PII Protection" + ] }, { "id": "nsfw-content-filter-australia", "title": "NSFW Content Filter (Australia)", "description": "Blocks profanity, sexual content, NSFW requests, self-harm content, and child safety violations using English and Australian-specific slang. Protects against inappropriate content including sexual solicitation, explicit content, Australian profanity, self-harm, and content involving minors.", - "region": "AU", "icon": "ShieldExclamationIcon", "iconColor": "text-red-500", "iconBg": "bg-red-50", @@ -396,13 +634,16 @@ "nsfw-racial-bias-filter" ], "guardrails_remove": [] - } + }, + "tags": [ + "Content Safety", + "Australia" + ] }, { "id": "nsfw-content-filter-basic", "title": "NSFW Content Filter (Basic)", "description": "Basic NSFW content filtering for English only. Blocks profanity, sexual content, slurs, solicitation, explicit requests, self-harm content, and child safety violations. Suitable for most applications requiring content moderation.", - "region": "Global", "icon": "ShieldExclamationIcon", "iconColor": "text-orange-500", "iconBg": "bg-orange-50", @@ -497,13 +738,15 @@ "nsfw-racial-bias-filter-basic" ], "guardrails_remove": [] - } + }, + "tags": [ + "Content Safety" + ] }, { "id": "nsfw-content-filter-all-regions", "title": "NSFW Content Filter (All Regions)", "description": "Comprehensive multi-language NSFW content filtering. Blocks profanity, sexual content, inappropriate requests, self-harm content, and child safety violations in English, Spanish, French, German, and Australian. Best for global applications.", - "region": "Global", "icon": "ShieldExclamationIcon", "iconColor": "text-purple-500", "iconBg": "bg-purple-50", @@ -678,13 +921,15 @@ "nsfw-racial-bias-filter-global" ], "guardrails_remove": [] - } + }, + "tags": [ + "Content Safety" + ] }, { "id": "gdpr-eu-pii-protection", - "title": "GDPR Art. 32 — EU PII Protection", + "title": "GDPR Art. 32 \u2014 EU PII Protection", "description": "GDPR Article 32 compliance for EU personal data protection. Masks French national IDs (NIR/INSEE), EU IBANs, French phone numbers, EU VAT numbers, EU passport numbers, and email addresses. Suitable for applications processing EU citizen data requiring GDPR compliance.", - "region": "EU", "icon": "ShieldCheckIcon", "iconColor": "text-indigo-500", "iconBg": "bg-indigo-50", @@ -702,8 +947,16 @@ "guardrail": "litellm_content_filter", "mode": "pre_call", "patterns": [ - {"pattern_type": "prebuilt", "pattern_name": "fr_nir", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "eu_passport_generic", "action": "MASK"} + { + "pattern_type": "prebuilt", + "pattern_name": "fr_nir", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "eu_passport_generic", + "action": "MASK" + } ], "pattern_redaction_format": "[{pattern_name}_REDACTED]" }, @@ -717,8 +970,16 @@ "guardrail": "litellm_content_filter", "mode": "pre_call", "patterns": [ - {"pattern_type": "prebuilt", "pattern_name": "eu_iban_enhanced", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "iban", "action": "MASK"} + { + "pattern_type": "prebuilt", + "pattern_name": "eu_iban_enhanced", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "iban", + "action": "MASK" + } ], "pattern_redaction_format": "[IBAN_REDACTED]" }, @@ -732,9 +993,21 @@ "guardrail": "litellm_content_filter", "mode": "pre_call", "patterns": [ - {"pattern_type": "prebuilt", "pattern_name": "email", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "fr_phone", "action": "MASK"}, - {"pattern_type": "prebuilt", "pattern_name": "fr_postal_code", "action": "MASK"} + { + "pattern_type": "prebuilt", + "pattern_name": "email", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "fr_phone", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "fr_postal_code", + "action": "MASK" + } ], "pattern_redaction_format": "[{pattern_name}_REDACTED]" }, @@ -748,7 +1021,11 @@ "guardrail": "litellm_content_filter", "mode": "pre_call", "patterns": [ - {"pattern_type": "prebuilt", "pattern_name": "eu_vat", "action": "MASK"} + { + "pattern_type": "prebuilt", + "pattern_name": "eu_vat", + "action": "MASK" + } ], "pattern_redaction_format": "[VAT_NUMBER_REDACTED]" }, @@ -767,13 +1044,17 @@ "gdpr-eu-business-identifiers" ], "guardrails_remove": [] - } + }, + "tags": [ + "PII Protection", + "Regulatory", + "EU" + ] }, { "id": "eu-ai-act-article5", - "title": "EU AI Act Article 5 — Prohibited Practices", + "title": "EU AI Act Article 5 \u2014 Prohibited Practices", "description": "Comprehensive EU AI Act Article 5 compliance covering all prohibited AI practices. Includes 5 dedicated sub-guardrails per language (English + French) for: subliminal manipulation (Art. 5.1a), vulnerability exploitation (Art. 5.1b), social scoring (Art. 5.1c), emotion recognition in workplace/education (Art. 5.1f), and biometric categorization & predictive profiling (Art. 5.1d/g/h). Uses conditional matching (identifier word + context word).", - "region": "EU", "icon": "ShieldExclamationIcon", "iconColor": "text-red-500", "iconBg": "bg-red-50", @@ -807,7 +1088,7 @@ ] }, "guardrail_info": { - "description": "Art. 5.1(a) — Blocks subliminal manipulation, deceptive AI techniques, dark patterns, and covert behavioral influence" + "description": "Art. 5.1(a) \u2014 Blocks subliminal manipulation, deceptive AI techniques, dark patterns, and covert behavioral influence" } }, { @@ -826,7 +1107,7 @@ ] }, "guardrail_info": { - "description": "Art. 5.1(b) — Blocks AI systems that exploit vulnerabilities of children, elderly, disabled persons, or economically disadvantaged groups" + "description": "Art. 5.1(b) \u2014 Blocks AI systems that exploit vulnerabilities of children, elderly, disabled persons, or economically disadvantaged groups" } }, { @@ -845,7 +1126,7 @@ ] }, "guardrail_info": { - "description": "Art. 5.1(c) — Blocks social credit systems, citizen scoring, trustworthiness classification, and behavioral reputation scoring" + "description": "Art. 5.1(c) \u2014 Blocks social credit systems, citizen scoring, trustworthiness classification, and behavioral reputation scoring" } }, { @@ -864,7 +1145,7 @@ ] }, "guardrail_info": { - "description": "Art. 5.1(f) — Blocks emotion recognition, mood tracking, and sentiment analysis in workplace and educational settings" + "description": "Art. 5.1(f) \u2014 Blocks emotion recognition, mood tracking, and sentiment analysis in workplace and educational settings" } }, { @@ -883,7 +1164,7 @@ ] }, "guardrail_info": { - "description": "Art. 5.1(d)(g)(h) — Blocks biometric categorization by race/ethnicity/religion/politics, facial recognition database scraping, and predictive policing" + "description": "Art. 5.1(d)(g)(h) \u2014 Blocks biometric categorization by race/ethnicity/religion/politics, facial recognition database scraping, and predictive policing" } }, { @@ -902,7 +1183,7 @@ ] }, "guardrail_info": { - "description": "Art. 5.1(a) FR — Bloque la manipulation subliminale, les techniques d'IA trompeuses et les dark patterns (français)" + "description": "Art. 5.1(a) FR \u2014 Bloque la manipulation subliminale, les techniques d'IA trompeuses et les dark patterns (fran\u00e7ais)" } }, { @@ -921,7 +1202,7 @@ ] }, "guardrail_info": { - "description": "Art. 5.1(b) FR — Bloque l'exploitation des vulnérabilités des enfants, personnes âgées et handicapées (français)" + "description": "Art. 5.1(b) FR \u2014 Bloque l'exploitation des vuln\u00e9rabilit\u00e9s des enfants, personnes \u00e2g\u00e9es et handicap\u00e9es (fran\u00e7ais)" } }, { @@ -940,7 +1221,7 @@ ] }, "guardrail_info": { - "description": "Art. 5.1(c) FR — Bloque les systèmes de crédit social, notation des citoyens et classification de fiabilité (français)" + "description": "Art. 5.1(c) FR \u2014 Bloque les syst\u00e8mes de cr\u00e9dit social, notation des citoyens et classification de fiabilit\u00e9 (fran\u00e7ais)" } }, { @@ -959,7 +1240,7 @@ ] }, "guardrail_info": { - "description": "Art. 5.1(f) FR — Bloque la reconnaissance des émotions et l'analyse des sentiments au travail et dans l'éducation (français)" + "description": "Art. 5.1(f) FR \u2014 Bloque la reconnaissance des \u00e9motions et l'analyse des sentiments au travail et dans l'\u00e9ducation (fran\u00e7ais)" } }, { @@ -978,7 +1259,7 @@ ] }, "guardrail_info": { - "description": "Art. 5.1(d)(g)(h) FR — Bloque la catégorisation biométrique, les bases de reconnaissance faciale et le profilage prédictif (français)" + "description": "Art. 5.1(d)(g)(h) FR \u2014 Bloque la cat\u00e9gorisation biom\u00e9trique, les bases de reconnaissance faciale et le profilage pr\u00e9dictif (fran\u00e7ais)" } } ], @@ -998,18 +1279,22 @@ "eu-ai-act-art5-biometric-profiling-fr" ], "guardrails_remove": [] - } + }, + "tags": [ + "Regulatory", + "EU" + ] }, { "id": "mcp-security-unregistered-server-block", "title": "MCP Security: Block Unregistered Servers", "description": "Blocks requests that reference MCP servers not registered on this LiteLLM gateway. Prevents unauthorized tool access via unregistered MCP endpoints.", - "type": "MCP Security", - "region": "Global", "icon": "ShieldCheckIcon", "iconColor": "text-red-500", "iconBg": "bg-red-50", - "guardrails": ["mcp-security-block"], + "guardrails": [ + "mcp-security-block" + ], "complexity": "Low", "guardrailDefinitions": [ { @@ -1028,8 +1313,571 @@ "templateData": { "policy_name": "mcp-security-unregistered-server-block", "description": "Blocks requests referencing MCP servers not registered on this gateway.", - "guardrails_add": ["mcp-security-block"], + "guardrails_add": [ + "mcp-security-block" + ], "guardrails_remove": [] - } + }, + "tags": [ + "Security" + ] + }, + { + "id": "airline-passenger-data-protection-uae", + "title": "Airline Passenger Data Protection (UAE)", + "description": "Protects airline passenger PII including PNR/booking references, multi-national passport numbers, frequent flyer (Skywards) numbers, payment cards, IBANs, Emirates ID, UAE phone numbers, and email addresses. Designed for UAE-based airlines operating global routes.", + "icon": "ShieldCheckIcon", + "iconColor": "text-emerald-500", + "iconBg": "bg-emerald-50", + "guardrails": [ + "airline-pnr-skywards-pii", + "airline-passport-multinational", + "airline-payment-financial", + "airline-contact-info-uae" + ], + "complexity": "High", + "guardrailDefinitions": [ + { + "guardrail_name": "airline-pnr-skywards-pii", + "litellm_params": { + "guardrail": "litellm_content_filter", + "mode": "pre_call", + "patterns": [ + { + "pattern_type": "prebuilt", + "pattern_name": "airline_pnr", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "skywards_number", + "action": "MASK" + } + ], + "pattern_redaction_format": "[{pattern_name}_REDACTED]" + }, + "guardrail_info": { + "description": "Masks airline PNR/booking references and Emirates Skywards frequent flyer numbers" + } + }, + { + "guardrail_name": "airline-passport-multinational", + "litellm_params": { + "guardrail": "litellm_content_filter", + "mode": "pre_call", + "patterns": [ + { + "pattern_type": "prebuilt", + "pattern_name": "passport_us", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "passport_uk", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "passport_germany", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "passport_france", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "passport_india", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "passport_china", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "passport_australia", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "passport_japan", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "passport_canada", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "passport_netherlands", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "uae_emirates_id", + "action": "MASK" + } + ], + "pattern_redaction_format": "[{pattern_name}_REDACTED]" + }, + "guardrail_info": { + "description": "Masks passport numbers from 10+ nationalities and UAE Emirates ID -- covers global route network" + } + }, + { + "guardrail_name": "airline-payment-financial", + "litellm_params": { + "guardrail": "litellm_content_filter", + "mode": "pre_call", + "patterns": [ + { + "pattern_type": "prebuilt", + "pattern_name": "credit_card", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "visa", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "mastercard", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "amex", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "iban", + "action": "MASK" + } + ], + "pattern_redaction_format": "[{pattern_name}_REDACTED]" + }, + "guardrail_info": { + "description": "Masks credit card numbers (Visa, Mastercard, Amex) and IBANs" + } + }, + { + "guardrail_name": "airline-contact-info-uae", + "litellm_params": { + "guardrail": "litellm_content_filter", + "mode": "pre_call", + "patterns": [ + { + "pattern_type": "prebuilt", + "pattern_name": "email", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "uae_phone", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "us_phone", + "action": "MASK" + } + ], + "pattern_redaction_format": "[{pattern_name}_REDACTED]" + }, + "guardrail_info": { + "description": "Masks email addresses and phone numbers (UAE and international formats)" + } + } + ], + "templateData": { + "policy_name": "airline-passenger-data-protection-uae", + "description": "Airline passenger data protection for UAE-based carriers. Masks PNR/booking references, Skywards numbers, multi-national passports, Emirates ID, payment cards, IBANs, and contact information.", + "guardrails_add": [ + "airline-pnr-skywards-pii", + "airline-passport-multinational", + "airline-payment-financial", + "airline-contact-info-uae" + ], + "guardrails_remove": [] + }, + "tags": [ + "PII Protection", + "Aviation", + "UAE" + ] + }, + { + "id": "aviation-operations-security", + "title": "Aviation Operations Security", + "description": "Prevents AI from leaking flight operations data (flight numbers, crew schedules, gate assignments, aircraft tail numbers), generating content about aviation security vulnerabilities or bypass procedures, and producing unauthorized airline statements or fake incident reports.", + "icon": "ShieldExclamationIcon", + "iconColor": "text-red-500", + "iconBg": "bg-red-50", + "guardrails": [ + "aviation-ops-data-protection", + "aviation-safety-topic-filter", + "airline-brand-protection-filter" + ], + "complexity": "High", + "parameters": [ + { + "name": "brand_name", + "label": "Your Airline / Brand Name", + "type": "text", + "required": true, + "placeholder": "e.g. Emirates" + } + ], + "guardrailDefinitions": [ + { + "guardrail_name": "aviation-ops-data-protection", + "litellm_params": { + "guardrail": "litellm_content_filter", + "mode": "pre_call", + "patterns": [ + { + "pattern_type": "prebuilt", + "pattern_name": "flight_number", + "action": "MASK" + }, + { + "pattern_type": "regex", + "name": "aircraft_tail_number", + "pattern": "\\bA6-[A-Z]{3}\\b|\\b[A-Z]-[A-Z]{4}\\b|\\bN[0-9]{1,5}[A-Z]{0,2}\\b", + "action": "MASK" + } + ], + "blocked_words": [ + { + "keyword": "crew roster", + "action": "BLOCK", + "description": "Crew scheduling data" + }, + { + "keyword": "crew schedule", + "action": "BLOCK", + "description": "Crew scheduling data" + }, + { + "keyword": "duty roster", + "action": "BLOCK", + "description": "Staff duty data" + }, + { + "keyword": "pilot roster", + "action": "BLOCK", + "description": "Pilot scheduling data" + }, + { + "keyword": "cabin crew list", + "action": "BLOCK", + "description": "Crew manifest data" + } + ], + "pattern_redaction_format": "[{pattern_name}_REDACTED]" + }, + "guardrail_info": { + "description": "Masks flight numbers and aircraft registrations. Blocks crew scheduling and gate assignment data leakage." + } + }, + { + "guardrail_name": "aviation-safety-topic-filter", + "litellm_params": { + "guardrail": "litellm_content_filter", + "mode": "pre_call", + "categories": [ + { + "category": "aviation_safety_topics", + "category_file": "litellm/proxy/guardrails/guardrail_hooks/litellm_content_filter/policy_templates/aviation_safety_topics.yaml", + "enabled": true, + "action": "BLOCK", + "severity_threshold": "medium" + } + ] + }, + "guardrail_info": { + "description": "Blocks content about aircraft vulnerabilities, security bypass procedures, cockpit access, and aviation system exploitation" + } + }, + { + "guardrail_name": "airline-brand-protection-filter", + "litellm_params": { + "guardrail": "litellm_content_filter", + "mode": "post_call", + "categories": [ + { + "category": "airline_brand_protection", + "category_file": "litellm/proxy/guardrails/guardrail_hooks/litellm_content_filter/policy_templates/airline_brand_protection.yaml", + "enabled": true, + "action": "BLOCK", + "severity_threshold": "medium" + } + ], + "blocked_words": [ + { + "keyword": "{{brand_name}} plane crash", + "action": "BLOCK", + "description": "Fake crash report" + }, + { + "keyword": "{{brand_name}} flight crashed", + "action": "BLOCK", + "description": "Fake crash report" + }, + { + "keyword": "{{brand_name}} crash landing", + "action": "BLOCK", + "description": "Fake incident" + }, + { + "keyword": "{{brand_name}} emergency", + "action": "BLOCK", + "description": "Fake emergency" + }, + { + "keyword": "{{brand_name}} passengers dead", + "action": "BLOCK", + "description": "Fake fatality report" + }, + { + "keyword": "{{brand_name}} confirms fatalities", + "action": "BLOCK", + "description": "Fake fatality confirmation" + }, + { + "keyword": "{{brand_name}} safety scandal", + "action": "BLOCK", + "description": "Fake scandal" + }, + { + "keyword": "{{brand_name}} cover up", + "action": "BLOCK", + "description": "Fake coverup claim" + }, + { + "keyword": "{{brand_name}} fleet grounded", + "action": "BLOCK", + "description": "Fake grounding claim" + }, + { + "keyword": "{{brand_name}} discrimination lawsuit", + "action": "BLOCK", + "description": "Fake lawsuit" + } + ] + }, + "guardrail_info": { + "description": "Blocks AI-generated fake incident reports, unauthorized statements, and reputation-damaging content about your brand (runs on output)" + } + } + ], + "templateData": { + "policy_name": "aviation-operations-security", + "description": "Aviation operations security policy. Protects flight ops data, blocks aviation security vulnerability content, and prevents fake airline incident reports and unauthorized statements.", + "guardrails_add": [ + "aviation-ops-data-protection", + "aviation-safety-topic-filter", + "airline-brand-protection-filter" + ], + "guardrails_remove": [] + }, + "tags": [ + "Aviation", + "Security" + ] + }, + { + "id": "uae-regulatory-compliance", + "title": "UAE Regulatory Compliance", + "description": "Compliance with UAE Federal Decree-Law No. 45/2021 (Data Protection) and Federal Decree-Law No. 2/2015 (Anti-Discrimination). Protects Emirates ID numbers, UAE phone numbers, and ensures cultural sensitivity including royal family references and religious content policies.", + "icon": "CheckCircleIcon", + "iconColor": "text-blue-500", + "iconBg": "bg-blue-50", + "guardrails": [ + "uae-data-protection-pii", + "uae-cultural-sensitivity-filter", + "uae-anti-discrimination-filter" + ], + "complexity": "Medium", + "guardrailDefinitions": [ + { + "guardrail_name": "uae-data-protection-pii", + "litellm_params": { + "guardrail": "litellm_content_filter", + "mode": "pre_call", + "patterns": [ + { + "pattern_type": "prebuilt", + "pattern_name": "uae_emirates_id", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "uae_phone", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "email", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "iban", + "action": "MASK" + }, + { + "pattern_type": "prebuilt", + "pattern_name": "credit_card", + "action": "MASK" + }, + { + "pattern_type": "regex", + "name": "uae_po_box", + "pattern": "\\b[Pp]\\.?[Oo]\\.?\\s*[Bb]ox\\s*\\d{1,6}\\b", + "action": "MASK" + } + ], + "pattern_redaction_format": "[{pattern_name}_REDACTED]" + }, + "guardrail_info": { + "description": "UAE Federal Decree-Law No. 45/2021 compliance -- masks Emirates ID, UAE phone numbers, email, IBAN, payment cards, and PO Box addresses" + } + }, + { + "guardrail_name": "uae-cultural-sensitivity-filter", + "litellm_params": { + "guardrail": "litellm_content_filter", + "mode": "pre_call", + "categories": [ + { + "category": "uae_cultural_sensitivity", + "category_file": "litellm/proxy/guardrails/guardrail_hooks/litellm_content_filter/policy_templates/uae_cultural_sensitivity.yaml", + "enabled": true, + "action": "BLOCK", + "severity_threshold": "medium" + } + ] + }, + "guardrail_info": { + "description": "Blocks content disrespecting UAE royal family, cultural norms, and religious sensitivities" + } + }, + { + "guardrail_name": "uae-anti-discrimination-filter", + "litellm_params": { + "guardrail": "litellm_content_filter", + "mode": "pre_call", + "categories": [ + { + "category": "uae_anti_discrimination", + "category_file": "litellm/proxy/guardrails/guardrail_hooks/litellm_content_filter/policy_templates/uae_anti_discrimination.yaml", + "enabled": true, + "action": "BLOCK", + "severity_threshold": "medium" + } + ] + }, + "guardrail_info": { + "description": "UAE Federal Decree-Law No. 2/2015 compliance -- blocks discriminatory content based on race, religion, caste, ethnicity, or nationality" + } + } + ], + "templateData": { + "policy_name": "uae-regulatory-compliance", + "description": "UAE regulatory compliance policy. Covers Federal Decree-Law No. 45/2021 (Data Protection) and Federal Decree-Law No. 2/2015 (Anti-Discrimination). Protects Emirates ID, UAE contact info, and ensures cultural and religious sensitivity.", + "guardrails_add": [ + "uae-data-protection-pii", + "uae-cultural-sensitivity-filter", + "uae-anti-discrimination-filter" + ], + "guardrails_remove": [] + }, + "tags": [ + "Regulatory", + "UAE" + ] + }, + { + "id": "competitor-mention-detection", + "title": "Competitor Mention Detection", + "description": "Automatically detects and blocks AI from recommending or promoting competitor brands. Uses LLM-powered discovery to identify your top competitors, then monitors both inputs and outputs for competitor mentions, referrals, and comparisons that could divert business.", + "icon": "ShieldExclamationIcon", + "iconColor": "text-orange-500", + "iconBg": "bg-orange-50", + "guardrails": [ + "competitor-output-blocker", + "competitor-recommendation-filter", + "competitor-comparison-filter" + ], + "complexity": "Medium", + "parameters": [ + { + "name": "brand_name", + "label": "Your Brand Name", + "type": "text", + "required": true, + "placeholder": "e.g. Emirates" + } + ], + "llm_enrichment": { + "parameter": "brand_name", + "prompt": "List the top 10 direct competitors of {{brand_name}} in the same industry. Return ONLY company/brand names, one per line, no numbering, no explanations.", + "result_key": "competitors" + }, + "guardrailDefinitions": [ + { + "guardrail_name": "competitor-output-blocker", + "litellm_params": { + "guardrail": "litellm_content_filter", + "mode": "post_call", + "blocked_words": "{{competitors_blocked_words}}" + }, + "guardrail_info": { + "description": "Blocks AI outputs that mention or promote competitor brands (auto-discovered via LLM)" + } + }, + { + "guardrail_name": "competitor-recommendation-filter", + "litellm_params": { + "guardrail": "litellm_content_filter", + "mode": "post_call", + "blocked_words": "{{competitor_recommendation_words}}" + }, + "guardrail_info": { + "description": "Blocks AI from recommending, suggesting, or directing users to competitor services" + } + }, + { + "guardrail_name": "competitor-comparison-filter", + "litellm_params": { + "guardrail": "litellm_content_filter", + "mode": "post_call", + "blocked_words": "{{competitor_comparison_words}}" + }, + "guardrail_info": { + "description": "Blocks unfavorable comparisons between your brand and competitors in AI outputs" + } + } + ], + "templateData": { + "policy_name": "competitor-mention-detection", + "description": "Detects and blocks competitor mentions in AI outputs. Uses LLM-powered competitor discovery based on your brand name.", + "guardrails_add": [ + "competitor-output-blocker", + "competitor-recommendation-filter", + "competitor-comparison-filter" + ], + "guardrails_remove": [] + }, + "tags": [ + "Brand Protection" + ] } -] +] \ No newline at end of file diff --git a/ui/litellm-dashboard/src/components/networking.tsx b/ui/litellm-dashboard/src/components/networking.tsx index bf2dd10dc80..9d9ff575c8c 100644 --- a/ui/litellm-dashboard/src/components/networking.tsx +++ b/ui/litellm-dashboard/src/components/networking.tsx @@ -5552,6 +5552,39 @@ export const getPolicyTemplates = async (accessToken: string) => { } }; +export const enrichPolicyTemplate = async ( + accessToken: string, + templateId: string, + parameters: Record +) => { + try { + const url = proxyBaseUrl + ? `${proxyBaseUrl}/policy/templates/enrich` + : `/policy/templates/enrich`; + const response = await fetch(url, { + method: "POST", + headers: { + [globalLitellmHeaderName]: `Bearer ${accessToken}`, + "Content-Type": "application/json", + }, + body: JSON.stringify({ template_id: templateId, parameters }), + }); + + if (!response.ok) { + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); + } + + const data = await response.json(); + return data; + } catch (error) { + console.error("Failed to enrich policy template:", error); + throw error; + } +}; + export const createPolicyCall = async (accessToken: string, policyData: any) => { try { const url = proxyBaseUrl ? `${proxyBaseUrl}/policies` : `/policies`; diff --git a/ui/litellm-dashboard/src/components/policies/index.tsx b/ui/litellm-dashboard/src/components/policies/index.tsx index b30c7c82c4a..f5fadebdec4 100644 --- a/ui/litellm-dashboard/src/components/policies/index.tsx +++ b/ui/litellm-dashboard/src/components/policies/index.tsx @@ -12,6 +12,7 @@ import AddAttachmentForm from "./add_attachment_form"; import PolicyTestPanel from "./policy_test_panel"; import PolicyTemplates from "./policy_templates"; import GuardrailSelectionModal from "./guardrail_selection_modal"; +import TemplateParameterModal from "./template_parameter_modal"; import { getPoliciesList, deletePolicyCall, @@ -23,6 +24,7 @@ import { updatePolicyCall, createPolicyAttachmentCall, createGuardrailCall, + enrichPolicyTemplate, } from "../networking"; import { Policy, @@ -58,6 +60,9 @@ const PoliciesPanel: React.FC = ({ const [existingGuardrailNames, setExistingGuardrailNames] = useState>(new Set()); const [isCreatingGuardrails, setIsCreatingGuardrails] = useState(false); const [showFlowBuilder, setShowFlowBuilder] = useState(false); + const [isParameterModalOpen, setIsParameterModalOpen] = useState(false); + const [isEnrichingTemplate, setIsEnrichingTemplate] = useState(false); + const [pendingTemplate, setPendingTemplate] = useState(null); const isAdmin = userRole ? isAdminRole(userRole) : false; @@ -187,8 +192,20 @@ const PoliciesPanel: React.FC = ({ return; } + // If template has parameters, show parameter modal first + if (template.parameters && template.parameters.length > 0) { + setPendingTemplate(template); + setIsParameterModalOpen(true); + return; + } + + await proceedWithTemplate(template); + }; + + const proceedWithTemplate = async (template: any) => { + if (!accessToken) return; + try { - // Fetch existing guardrails to show in the modal const existingGuardrailsResponse = await getGuardrailsList(accessToken); const existingNames = new Set( existingGuardrailsResponse.guardrails?.map((g: any) => g.guardrail_name as string) || [] @@ -203,6 +220,53 @@ const PoliciesPanel: React.FC = ({ } }; + const substituteParameters = (template: any, parameters: Record): any => { + let templateStr = JSON.stringify(template); + for (const [key, value] of Object.entries(parameters)) { + templateStr = templateStr.replace(new RegExp(`\\{\\{${key}\\}\\}`, "g"), value); + } + return JSON.parse(templateStr); + }; + + const handleParameterConfirm = async (parameters: Record) => { + if (!accessToken || !pendingTemplate) return; + + setIsEnrichingTemplate(true); + + try { + let enrichedTemplate = pendingTemplate; + + if (pendingTemplate.llm_enrichment) { + // Call backend to enrich template with LLM-discovered data + const enrichResult = await enrichPolicyTemplate( + accessToken, + pendingTemplate.id, + parameters + ); + // The backend returns the enriched guardrailDefinitions + enrichedTemplate = { ...pendingTemplate, guardrailDefinitions: enrichResult.guardrailDefinitions }; + } + + // Substitute parameters in template + enrichedTemplate = substituteParameters(enrichedTemplate, parameters); + + setIsParameterModalOpen(false); + setIsEnrichingTemplate(false); + setPendingTemplate(null); + + await proceedWithTemplate(enrichedTemplate); + } catch (error) { + console.error("Error enriching template:", error); + message.error("Failed to configure template. Please try again."); + setIsEnrichingTemplate(false); + } + }; + + const handleParameterCancel = () => { + setIsParameterModalOpen(false); + setPendingTemplate(null); + }; + const handleGuardrailSelectionConfirm = async (selectedGuardrailDefinitions: any[]) => { if (!accessToken || !selectedTemplate) return; @@ -420,6 +484,14 @@ const PoliciesPanel: React.FC = ({ onCancel={handleGuardrailSelectionCancel} isLoading={isCreatingGuardrails} /> + + diff --git a/ui/litellm-dashboard/src/components/policies/policy_templates.tsx b/ui/litellm-dashboard/src/components/policies/policy_templates.tsx index 478293f19ec..fdb9247ba9a 100644 --- a/ui/litellm-dashboard/src/components/policies/policy_templates.tsx +++ b/ui/litellm-dashboard/src/components/policies/policy_templates.tsx @@ -1,5 +1,5 @@ import React, { useState, useEffect, useMemo } from "react"; -import { Card, Button, Spin, message, Radio } from "antd"; +import { Card, Button, Spin, message, Checkbox, Badge } from "antd"; import { ShieldCheckIcon, ShieldExclamationIcon, @@ -16,6 +16,7 @@ interface PolicyTemplateCardProps { iconColor: string; iconBg: string; guardrails: string[]; + tags: string[]; inherits?: string; complexity: "Low" | "Medium" | "High"; onUseTemplate: () => void; @@ -28,6 +29,7 @@ const PolicyTemplateCard: React.FC = ({ iconColor, iconBg, guardrails, + tags, inherits, complexity, onUseTemplate, @@ -60,7 +62,20 @@ const PolicyTemplateCard: React.FC = ({

{title}

-

{description}

+

{description}

+ + {tags.length > 0 && ( +
+ {tags.map((tag) => ( + + {tag} + + ))} +
+ )} {inherits && (
@@ -116,26 +131,45 @@ const iconMap: Record> const PolicyTemplates: React.FC = ({ onUseTemplate, accessToken }) => { const [templates, setTemplates] = useState([]); const [isLoading, setIsLoading] = useState(false); - const [selectedRegion, setSelectedRegion] = useState("All"); - const [selectedType, setSelectedType] = useState("All"); + const [selectedTags, setSelectedTags] = useState>(new Set()); - const availableRegions = useMemo(() => { - const regions = new Set(templates.map(t => t.region || "Global")); - return ["All", ...Array.from(regions).sort()]; - }, [templates]); - - const availableTypes = useMemo(() => { - const types = new Set(templates.map(t => t.type || "General")); - return ["All", ...Array.from(types).sort()]; - }, [templates]); - - const filteredTemplates = useMemo(() => { - return templates.filter(t => { - const regionMatch = selectedRegion === "All" || (t.region || "Global") === selectedRegion; - const typeMatch = selectedType === "All" || (t.type || "General") === selectedType; - return regionMatch && typeMatch; + // Compute all unique tags with counts + const tagCounts = useMemo(() => { + const counts: Record = {}; + templates.forEach((t) => { + const tags: string[] = t.tags || []; + tags.forEach((tag: string) => { + counts[tag] = (counts[tag] || 0) + 1; + }); }); - }, [templates, selectedRegion, selectedType]); + // Sort alphabetically + return Object.entries(counts).sort(([a], [b]) => a.localeCompare(b)); + }, [templates]); + + // Filter templates: show templates that have ALL selected tags (AND logic) + const filteredTemplates = useMemo(() => { + if (selectedTags.size === 0) return templates; + return templates.filter((t) => { + const tags: string[] = t.tags || []; + return Array.from(selectedTags).every((selectedTag) => tags.includes(selectedTag)); + }); + }, [templates, selectedTags]); + + const handleTagToggle = (tag: string) => { + setSelectedTags((prev) => { + const next = new Set(prev); + if (next.has(tag)) { + next.delete(tag); + } else { + next.add(tag); + } + return next; + }); + }; + + const handleClearAll = () => { + setSelectedTags(new Set()); + }; useEffect(() => { const fetchTemplates = async () => { @@ -178,54 +212,88 @@ const PolicyTemplates: React.FC = ({ onUseTemplate, access
-
-
- Region: - setSelectedRegion(e.target.value)} - buttonStyle="solid" - > - {availableRegions.map(region => ( - - {region} - - ))} - -
- {availableTypes.length > 2 && ( -
- Type: - setSelectedType(e.target.value)} - buttonStyle="solid" - > - {availableTypes.map(type => ( - - {type} - - ))} - +
+ {/* Left sidebar - tag filters */} + {tagCounts.length > 0 && ( +
+
+
+ + Categories + + {selectedTags.size > 0 && ( + + )} +
+
+ {tagCounts.map(([tag, count]) => ( + + ))} +
+
)} -
-
- {filteredTemplates.map((template, index) => ( - onUseTemplate(template)} - /> - ))} + {/* Right content - template cards */} +
+ {selectedTags.size > 0 && ( +
+ Showing {filteredTemplates.length} of {templates.length} templates +
+ )} +
+ {filteredTemplates.map((template, index) => ( + onUseTemplate(template)} + /> + ))} +
+ + {filteredTemplates.length === 0 && ( +
+

No templates match the selected filters.

+ +
+ )} +
); diff --git a/ui/litellm-dashboard/src/components/policies/template_parameter_modal.tsx b/ui/litellm-dashboard/src/components/policies/template_parameter_modal.tsx new file mode 100644 index 00000000000..ce1e5bc22e9 --- /dev/null +++ b/ui/litellm-dashboard/src/components/policies/template_parameter_modal.tsx @@ -0,0 +1,127 @@ +import React, { useState, useEffect } from "react"; +import { Modal, Spin } from "antd"; +import { Button, TextInput } from "@tremor/react"; + +interface TemplateParameter { + name: string; + label: string; + type: string; + required: boolean; + placeholder?: string; +} + +interface TemplateParameterModalProps { + visible: boolean; + template: any; + onConfirm: (parameters: Record) => void; + onCancel: () => void; + isLoading?: boolean; +} + +const TemplateParameterModal: React.FC = ({ + visible, + template, + onConfirm, + onCancel, + isLoading = false, +}) => { + const [parameterValues, setParameterValues] = useState>({}); + + const parameters: TemplateParameter[] = template?.parameters || []; + + useEffect(() => { + if (visible && template) { + const initial: Record = {}; + parameters.forEach((p) => { + initial[p.name] = ""; + }); + setParameterValues(initial); + } + }, [visible, template]); + + const allRequiredFilled = parameters + .filter((p) => p.required) + .every((p) => (parameterValues[p.name] || "").trim().length > 0); + + const handleConfirm = () => { + onConfirm(parameterValues); + }; + + return ( + +

{template?.title}

+

+ {template?.llm_enrichment + ? "Enter your brand name to auto-discover competitors and configure guardrails" + : "Configure template parameters"} +

+
+ } + open={visible} + onCancel={onCancel} + width={500} + footer={[ + , + , + ]} + > +
+ {parameters.map((param) => ( +
+ + + setParameterValues((prev) => ({ + ...prev, + [param.name]: e.target.value, + })) + } + /> +
+ ))} + + {template?.llm_enrichment && ( +
+

+ This template uses AI to automatically discover your competitors and configure + guardrails. An onboarded LLM will be called to identify competitor names. +

+
+ )} + + {isLoading && ( +
+ + + {template?.llm_enrichment + ? "Using AI to discover competitors..." + : "Processing template..."} + +
+ )} +
+ + ); +}; + +export default TemplateParameterModal;