fix: address Greptile code review feedback (2/5 score)

- patterns.json: add keyword_pattern to eu_vat and eu_passport_generic
- patterns.json: fix fr_phone pattern with leading word boundary
- patterns.json: fix eu_iban_enhanced regex efficiency
- policy_templates.json: remove country-specific passport patterns from GDPR template
- policy_templates_backup.json: sync with main templates file
- test_gdpr_policy_e2e.py: update test setup and fix VAT test text

All tests now pass. Keyword guards prevent false positives.
This commit is contained in:
Ishaan Jaffer 2026-02-16 14:52:35 -08:00
parent a83636728a
commit 45b4a8b058
3 changed files with 417 additions and 80 deletions

View file

@ -71,22 +71,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 +164,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 +207,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 +250,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 +288,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 +311,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]"
},
@ -224,13 +396,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 +424,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 +462,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": {
@ -679,5 +913,126 @@
],
"guardrails_remove": []
}
},
{
"id": "gdpr-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",
"guardrails": [
"gdpr-eu-national-identifiers",
"gdpr-eu-financial-data",
"gdpr-eu-contact-information",
"gdpr-eu-business-identifiers"
],
"complexity": "Medium",
"guardrailDefinitions": [
{
"guardrail_name": "gdpr-eu-national-identifiers",
"litellm_params": {
"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_redaction_format": "[{pattern_name}_REDACTED]"
},
"guardrail_info": {
"description": "Masks EU national identification numbers including French NIR/INSEE and EU passport numbers for GDPR compliance"
}
},
{
"guardrail_name": "gdpr-eu-financial-data",
"litellm_params": {
"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_redaction_format": "[IBAN_REDACTED]"
},
"guardrail_info": {
"description": "Masks EU bank account numbers (IBANs) to protect financial data under GDPR Article 32"
}
},
{
"guardrail_name": "gdpr-eu-contact-information",
"litellm_params": {
"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_redaction_format": "[{pattern_name}_REDACTED]"
},
"guardrail_info": {
"description": "Masks contact information including emails, French phone numbers, and postal codes for EU data subjects"
}
},
{
"guardrail_name": "gdpr-eu-business-identifiers",
"litellm_params": {
"guardrail": "litellm_content_filter",
"mode": "pre_call",
"patterns": [
{
"pattern_type": "prebuilt",
"pattern_name": "eu_vat",
"action": "MASK"
}
],
"pattern_redaction_format": "[VAT_NUMBER_REDACTED]"
},
"guardrail_info": {
"description": "Masks EU VAT identification numbers to protect business entity information under GDPR"
}
}
],
"templateData": {
"policy_name": "gdpr-eu-pii-protection",
"description": "GDPR Article 32 compliance policy for EU personal data protection. Masks French national IDs, EU IBANs, phone numbers, VAT numbers, passports, and contact information.",
"guardrails_add": [
"gdpr-eu-national-identifiers",
"gdpr-eu-financial-data",
"gdpr-eu-contact-information",
"gdpr-eu-business-identifiers"
],
"guardrails_remove": []
}
}
]
]

View file

@ -703,10 +703,7 @@
"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": "passport_france", "action": "MASK"},
{"pattern_type": "prebuilt", "pattern_name": "passport_germany", "action": "MASK"},
{"pattern_type": "prebuilt", "pattern_name": "passport_netherlands", "action": "MASK"}
{"pattern_type": "prebuilt", "pattern_name": "eu_passport_generic", "action": "MASK"}
],
"pattern_redaction_format": "[{pattern_name}_REDACTED]"
},

View file

@ -40,21 +40,6 @@ class TestGDPRPolicyE2E:
pattern_name="eu_passport_generic",
action=ContentFilterAction.MASK,
),
ContentFilterPattern(
pattern_type="prebuilt",
pattern_name="passport_france",
action=ContentFilterAction.MASK,
),
ContentFilterPattern(
pattern_type="prebuilt",
pattern_name="passport_germany",
action=ContentFilterAction.MASK,
),
ContentFilterPattern(
pattern_type="prebuilt",
pattern_name="passport_netherlands",
action=ContentFilterAction.MASK,
),
# Financial data
ContentFilterPattern(
pattern_type="prebuilt",