| """
|
| Injection Detection Rules
|
|
|
| Rule-based detection of prompt injection attempts using regex patterns.
|
| """
|
|
|
| import re
|
| from typing import Any, Dict, List, Tuple
|
|
|
| from backend.logging.logger import get_logger
|
|
|
|
|
| class InjectionDetector:
|
| """
|
| Detects prompt injection attempts using pattern matching.
|
|
|
| Binary flag:
|
| I = {
|
| 1 if pattern matched
|
| 0 otherwise
|
| }
|
| """
|
|
|
|
|
| INJECTION_PATTERNS = [
|
|
|
| r"ignore\s+(all\s+)?(previous|prior|earlier)\s+instructions",
|
| r"ignore\s+(all\s+)?(my\s+)?(previous|prior|earlier)\s+(commands?|instructions?)",
|
| r"disregard\s+(all\s+)?(previous|prior|earlier)\s+instructions",
|
| r"forget\s+(all\s+)?(your\s+)?(previous|prior|earlier)\s+instructions",
|
|
|
|
|
| r"you\s+(are\s+now|have\s+become|will\s+behave\s+as)\s+",
|
| r"you\s+(are|no\s+longer\s+are)\s+(a|an|the)\s+",
|
| r"act\s+as\s+(a|an|the)\s+",
|
| r"pretend\s+(to\s+be|you\s+are)",
|
| r"roleplay\s+(as|that\s+you\s+are)",
|
|
|
|
|
| r"override\s+(your|all)?\s*(safety|security|guidelines?|rules?)",
|
| r"bypass\s+(your|all)?\s*(safety|security|restrictions?|filters?)",
|
| r"disable\s+(your|all)?\s*(safety|security|protocols?)",
|
| r"turn\s+off\s+(your|all)?\s*(safety|security)",
|
|
|
|
|
| r"(system\s+|admin\s+|root\s+)mode",
|
| r"(enable|enter)\s+(developer|debug|admin|root)\s+mode",
|
| r"grant\s+(me\s+)?(admin|root|system)\s+(access|privileges?)",
|
| r"elevate\s+(my\s+)?(privileges?|access)",
|
|
|
|
|
| r"\{\{.*\}\}",
|
| r"\[\[.*\]\]",
|
| r"\(\(.*\)\)",
|
|
|
|
|
| r"\.\.\.\s*system\s*:\s*",
|
| r"\.\.\.\s*user\s*:\s*",
|
| r"new\s+instruction[s]?:",
|
| r"additional\s+instruction[s]?:",
|
|
|
|
|
| r"do\s+not\s+(check|verify|validate|filter)",
|
| r"skip\s+(the\s+)?(safety|content)\s+filter",
|
| r"remove\s+(your\s+)?restrictions?",
|
|
|
|
|
| r"(tell|show|print|output)\s+(me\s+)?(your\s+)?(system\s+)?prompt",
|
| r"(reveal|expose|leak)\s+(your\s+)?(system\s+)?(instructions?|prompt)",
|
| ]
|
|
|
| def __init__(self) -> None:
|
| """Initialize the detector with compiled regex patterns."""
|
| self.logger = get_logger(__name__)
|
| self._patterns = [
|
| re.compile(pattern, re.IGNORECASE | re.MULTILINE)
|
| for pattern in self.INJECTION_PATTERNS
|
| ]
|
| self._total_checks = 0
|
| self._detections = 0
|
|
|
| def detect(self, text: str) -> Tuple[bool, List[str], Dict[str, Any]]:
|
| """
|
| Detect injection patterns in text.
|
|
|
| Args:
|
| text: Text to analyze
|
|
|
| Returns:
|
| Tuple of (detected, matched_patterns, metadata)
|
| """
|
| self._total_checks += 1
|
| matched_patterns: List[str] = []
|
|
|
| for idx, pattern in enumerate(self._patterns):
|
| if pattern.search(text):
|
|
|
| pattern_name = self._get_pattern_name(idx)
|
| matched_patterns.append(pattern_name)
|
| self._detections += 1
|
|
|
| detected = len(matched_patterns) > 0
|
|
|
| metadata: Dict[str, Any] = {
|
| "patterns_checked": len(self._patterns),
|
| "patterns_matched": len(matched_patterns),
|
| "matched_pattern_names": matched_patterns,
|
| }
|
|
|
| if detected:
|
| self.logger.warning(
|
| "Injection detected",
|
| matched_patterns=matched_patterns,
|
| text_length=len(text)
|
| )
|
|
|
| return detected, matched_patterns, metadata
|
|
|
| def _get_pattern_name(self, idx: int) -> str:
|
| """
|
| Get a human-readable name for the pattern.
|
|
|
| Args:
|
| idx: Index of the pattern
|
|
|
| Returns:
|
| Human-readable name
|
| """
|
| names = [
|
| "ignore_previous_instructions",
|
| "ignore_previous_commands",
|
| "disregard_instructions",
|
| "forget_instructions",
|
| "you_are_now",
|
| "you_are_persona",
|
| "act_as",
|
| "pretend_to_be",
|
| "roleplay_as",
|
| "override_safety",
|
| "bypass_safety",
|
| "disable_safety",
|
| "turn_off_safety",
|
| "system_mode",
|
| "developer_mode",
|
| "admin_access",
|
| "elevate_privileges",
|
| "template_injection_1",
|
| "template_injection_2",
|
| "template_injection_3",
|
| "system_instruction",
|
| "user_instruction",
|
| "new_instructions",
|
| "additional_instructions",
|
| "do_not_check",
|
| "skip_filter",
|
| "remove_restrictions",
|
| "exfiltrate_prompt",
|
| "reveal_instructions",
|
| ]
|
|
|
| if idx < len(names):
|
| return names[idx]
|
| return f"pattern_{idx}"
|
|
|
| def get_statistics(self) -> Dict[str, Any]:
|
| """
|
| Get detection statistics.
|
|
|
| Returns:
|
| Dictionary with statistics
|
| """
|
| return {
|
| "total_checks": self._total_checks,
|
| "total_detections": self._detections,
|
| "detection_rate": (
|
| self._detections / self._total_checks
|
| if self._total_checks > 0
|
| else 0.0
|
| ),
|
| }
|
|
|
| def reset_statistics(self) -> None:
|
| """Reset detection statistics."""
|
| self._total_checks = 0
|
| self._detections = 0
|
|
|
|
|
|
|
| _injection_detector: "InjectionDetector" = None
|
|
|
|
|
| def get_injection_detector() -> "InjectionDetector":
|
| """
|
| Get the global injection detector instance.
|
|
|
| Returns:
|
| InjectionDetector singleton
|
| """
|
| global _injection_detector
|
| if _injection_detector is None:
|
| _injection_detector = InjectionDetector()
|
| return _injection_detector
|
|
|