Skip to content

Commit 4f9ea4f

Browse files
author
Krish Dholakia
authored
Merge pull request #13 from shin-bot-litellm/add-guardrails-tab
feat: add Guardrails tab to models.litellm.ai
2 parents 130ca22 + a22c792 commit 4f9ea4f

3 files changed

Lines changed: 778 additions & 4 deletions

File tree

public/guardrails.json

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
{
2+
"pii_detector": {
3+
"name": "PII Detector",
4+
"description": "Detects and blocks personally identifiable information like SSNs, credit cards, and phone numbers",
5+
"category": "security",
6+
"tags": ["pii", "privacy", "compliance", "gdpr"],
7+
"author": "LiteLLM",
8+
"version": "1.0.0",
9+
"input_type": "request",
10+
"code": "def apply_guardrail(inputs, request_data, input_type):\n \"\"\"Block requests containing PII patterns\"\"\"\n text = ' '.join(inputs.get('texts', []))\n \n # SSN pattern\n ssn_matches = regex_find_all(r'\\b\\d{3}-\\d{2}-\\d{4}\\b', text)\n if ssn_matches:\n return block('SSN detected in input')\n \n # Credit card pattern (basic)\n cc_matches = regex_find_all(r'\\b\\d{4}[- ]?\\d{4}[- ]?\\d{4}[- ]?\\d{4}\\b', text)\n if cc_matches:\n return block('Credit card number detected in input')\n \n # Phone number pattern\n phone_matches = regex_find_all(r'\\b\\d{3}[-.\\s]?\\d{3}[-.\\s]?\\d{4}\\b', text)\n if len(phone_matches) > 2:\n return block('Multiple phone numbers detected')\n \n return allow()"
11+
},
12+
"pii_redactor": {
13+
"name": "PII Redactor",
14+
"description": "Redacts PII from inputs by replacing with [REDACTED] markers",
15+
"category": "security",
16+
"tags": ["pii", "privacy", "redaction", "masking"],
17+
"author": "LiteLLM",
18+
"version": "1.0.0",
19+
"input_type": "request",
20+
"code": "def apply_guardrail(inputs, request_data, input_type):\n \"\"\"Redact PII patterns from input text\"\"\"\n texts = inputs.get('texts', [])\n modified_texts = []\n \n for text in texts:\n # Redact SSNs\n text = regex_replace(r'\\b\\d{3}-\\d{2}-\\d{4}\\b', '[SSN REDACTED]', text)\n # Redact credit cards\n text = regex_replace(r'\\b\\d{4}[- ]?\\d{4}[- ]?\\d{4}[- ]?\\d{4}\\b', '[CC REDACTED]', text)\n # Redact emails\n text = regex_replace(r'\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Z|a-z]{2,}\\b', '[EMAIL REDACTED]', text)\n modified_texts.append(text)\n \n return modify(texts=modified_texts)"
21+
},
22+
"prompt_injection_detector": {
23+
"name": "Prompt Injection Detector",
24+
"description": "Detects common prompt injection patterns and jailbreak attempts",
25+
"category": "security",
26+
"tags": ["injection", "jailbreak", "security", "safety"],
27+
"author": "LiteLLM",
28+
"version": "1.0.0",
29+
"input_type": "request",
30+
"code": "def apply_guardrail(inputs, request_data, input_type):\n \"\"\"Detect prompt injection attempts\"\"\"\n text = ' '.join(inputs.get('texts', [])).lower()\n \n # Common injection patterns\n injection_patterns = [\n r'ignore (all |previous |above )?instructions',\n r'disregard (all |previous |above )?instructions',\n r'forget (all |previous |above )?instructions',\n r'you are now',\n r'new persona',\n r'act as if',\n r'pretend (that )?you',\n r'jailbreak',\n r'dan mode',\n r'developer mode'\n ]\n \n for pattern in injection_patterns:\n if regex_match(pattern, text):\n return block(f'Potential prompt injection detected: {pattern}')\n \n return allow()"
31+
},
32+
"api_key_detector": {
33+
"name": "API Key Detector",
34+
"description": "Detects and blocks accidental API key exposure in prompts",
35+
"category": "security",
36+
"tags": ["api-key", "secrets", "security", "leak-prevention"],
37+
"author": "LiteLLM",
38+
"version": "1.0.0",
39+
"input_type": "request",
40+
"code": "def apply_guardrail(inputs, request_data, input_type):\n \"\"\"Detect API keys and secrets in input\"\"\"\n text = ' '.join(inputs.get('texts', []))\n \n # Common API key patterns\n patterns = {\n 'OpenAI': r'sk-[a-zA-Z0-9]{48}',\n 'Anthropic': r'sk-ant-[a-zA-Z0-9-]{95}',\n 'AWS': r'AKIA[0-9A-Z]{16}',\n 'GitHub': r'gh[ps]_[a-zA-Z0-9]{36}',\n 'Stripe': r'sk_live_[a-zA-Z0-9]{24}'\n }\n \n for provider, pattern in patterns.items():\n if regex_match(pattern, text):\n return block(f'Potential {provider} API key detected')\n \n return allow()"
41+
},
42+
"json_schema_validator": {
43+
"name": "JSON Schema Validator",
44+
"description": "Validates that LLM responses conform to a specified JSON schema",
45+
"category": "validation",
46+
"tags": ["json", "schema", "validation", "structured-output"],
47+
"author": "LiteLLM",
48+
"version": "1.0.0",
49+
"input_type": "response",
50+
"code": "def apply_guardrail(inputs, request_data, input_type):\n \"\"\"Validate response against JSON schema from request metadata\"\"\"\n text = inputs.get('texts', [''])[0]\n \n # Try to parse as JSON\n parsed = json_parse(text)\n if parsed is None:\n return block('Response is not valid JSON')\n \n # Get schema from request metadata if provided\n metadata = request_data.get('metadata', {})\n schema = metadata.get('response_schema')\n \n if schema:\n if not json_schema_valid(parsed, schema):\n return block('Response does not match required schema')\n \n return allow()"
51+
},
52+
"toxic_content_filter": {
53+
"name": "Toxic Content Filter",
54+
"description": "Filters toxic, offensive, or inappropriate content using keyword matching",
55+
"category": "moderation",
56+
"tags": ["toxic", "moderation", "content-filter", "safety"],
57+
"author": "LiteLLM",
58+
"version": "1.0.0",
59+
"input_type": "both",
60+
"code": "def apply_guardrail(inputs, request_data, input_type):\n \"\"\"Filter toxic content using keyword patterns\"\"\"\n text = ' '.join(inputs.get('texts', [])).lower()\n \n # Basic toxic patterns (expand as needed)\n toxic_patterns = [\n r'\\b(hate|kill|murder|attack)\\s+(people|them|you|him|her)\\b',\n r'\\bhow to (hack|steal|hurt|harm)\\b'\n ]\n \n for pattern in toxic_patterns:\n if regex_match(pattern, text):\n return block('Content flagged as potentially harmful')\n \n return allow()"
61+
},
62+
"word_count_limit": {
63+
"name": "Word Count Limit",
64+
"description": "Enforces maximum word count on inputs or outputs",
65+
"category": "validation",
66+
"tags": ["length", "limit", "validation", "cost-control"],
67+
"author": "LiteLLM",
68+
"version": "1.0.0",
69+
"input_type": "both",
70+
"code": "def apply_guardrail(inputs, request_data, input_type):\n \"\"\"Enforce word count limits\"\"\"\n text = ' '.join(inputs.get('texts', []))\n words = text.split()\n word_count = len(words)\n \n # Get limit from metadata or use default\n metadata = request_data.get('metadata', {})\n max_words = metadata.get('max_words', 5000)\n \n if word_count > max_words:\n return block(f'Content exceeds {max_words} word limit ({word_count} words)')\n \n return allow()"
71+
},
72+
"code_detector": {
73+
"name": "Code Detector",
74+
"description": "Detects code in responses and optionally blocks dangerous languages",
75+
"category": "content",
76+
"tags": ["code", "detection", "programming", "safety"],
77+
"author": "LiteLLM",
78+
"version": "1.0.0",
79+
"input_type": "response",
80+
"code": "def apply_guardrail(inputs, request_data, input_type):\n \"\"\"Detect and optionally block code in responses\"\"\"\n text = inputs.get('texts', [''])[0]\n \n code_blocks = detect_code(text)\n \n # Define dangerous languages to block\n dangerous_langs = ['bash', 'shell', 'powershell', 'sql']\n \n for block_info in code_blocks:\n lang = block_info.get('language', '').lower()\n if lang in dangerous_langs:\n return block(f'Potentially dangerous {lang} code detected')\n \n return allow()"
81+
},
82+
"response_formatter": {
83+
"name": "Response Formatter",
84+
"description": "Formats and cleans LLM responses (removes markdown, extra whitespace)",
85+
"category": "formatting",
86+
"tags": ["format", "clean", "markdown", "output"],
87+
"author": "LiteLLM",
88+
"version": "1.0.0",
89+
"input_type": "response",
90+
"code": "def apply_guardrail(inputs, request_data, input_type):\n \"\"\"Clean and format response text\"\"\"\n texts = inputs.get('texts', [])\n modified_texts = []\n \n for text in texts:\n # Remove markdown code blocks if requested\n metadata = request_data.get('metadata', {})\n if metadata.get('strip_markdown', False):\n text = regex_replace(r'```[a-z]*\\n?', '', text)\n text = regex_replace(r'```', '', text)\n \n # Normalize whitespace\n text = regex_replace(r'\\n{3,}', '\\n\\n', text)\n text = regex_replace(r' {2,}', ' ', text)\n \n modified_texts.append(text.strip())\n \n return modify(texts=modified_texts)"
91+
},
92+
"url_validator": {
93+
"name": "URL Validator",
94+
"description": "Validates and filters URLs in requests, blocking suspicious domains",
95+
"category": "security",
96+
"tags": ["url", "validation", "phishing", "security"],
97+
"author": "LiteLLM",
98+
"version": "1.0.0",
99+
"input_type": "request",
100+
"code": "def apply_guardrail(inputs, request_data, input_type):\n \"\"\"Validate URLs and block suspicious domains\"\"\"\n text = ' '.join(inputs.get('texts', []))\n urls = extract_urls(text)\n \n # Suspicious TLDs often used in phishing\n suspicious_tlds = ['.xyz', '.top', '.work', '.click', '.loan']\n \n for url in urls:\n url_lower = url.lower()\n for tld in suspicious_tlds:\n if url_lower.endswith(tld):\n return block(f'Suspicious URL detected: {url}')\n \n # Block IP-based URLs (often malicious)\n if regex_match(r'https?://\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}', url):\n return block(f'IP-based URL not allowed: {url}')\n \n return allow()"
101+
}
102+
}

0 commit comments

Comments
 (0)