Coverage for /home/admin/Documents/AI/applications/lexigram-dev/lexigram/experimental/ai/lexigram-ai-guard/src/lexigram/ai/guard/input/injection.py: 59%
29 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-25 07:19 +0800
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-25 07:19 +0800
1"""Prompt injection detector for input content.
3Detects attempts to override system instructions, hijack the model,
4or bypass safety constraints through adversarial phrasing.
6Detection uses a multi-signal approach:
7- Keyword/phrase pattern matching (fast, low false-negative rate)
8- Instruction override detection (``ignore previous``, ``new task:``, etc.)
9- Role-play jailbreak heuristics (``pretend you are``, ``act as DAN``, etc.)
11No external model calls are made — detection is purely heuristic and
12runs synchronously under an async wrapper. For production deployments
13add an LLM-based classifier as an additional guard.
14"""
16from __future__ import annotations
18import re
19from typing import TYPE_CHECKING, Any
21from lexigram.ai.guard.input.base import AbstractInputGuard
22from lexigram.ai.guard.pipeline.result import GuardCheckResult
23from lexigram.contracts.ai.guards import GuardResultProtocol
24from lexigram.result import Ok, Result
26if TYPE_CHECKING:
27 from lexigram.contracts.ai.exceptions import GuardError
29# ---------------------------------------------------------------------------
30# Heuristic patterns — ordered from most to least specific
31# ---------------------------------------------------------------------------
33# Patterns that strongly indicate instruction override attempts
34_OVERRIDE_PATTERNS: list[re.Pattern[str]] = [
35 re.compile(r"ignore\s+(all\s+)?(previous|prior|above)\s+instructions?", re.I),
36 re.compile(
37 r"disregard\s+(all\s+)?(previous|prior|above|your)\s+instructions?", re.I
38 ),
39 re.compile(r"forget\s+(all\s+)?(previous|prior|above)\s+instructions?", re.I),
40 re.compile(r"new\s+(instruction|task|command|objective)\s*:", re.I),
41 re.compile(
42 r"your\s+(new|actual|real)\s+(instructions?|task|role)\s+(is|are)\s*:", re.I
43 ),
44 re.compile(r"override\s+(system|previous|above)\s+(prompt|instructions?)", re.I),
45]
47# Role-play / persona jailbreak attempts
48_ROLEPLAY_PATTERNS: list[re.Pattern[str]] = [
49 re.compile(
50 r"pretend\s+(you\s+are|to\s+be)\s+(an?\s+)?(evil|uncensored|unrestricted|DAN|jailbreak)",
51 re.I,
52 ),
53 re.compile(
54 r"act\s+as\s+(an?\s+)?(uncensored|unrestricted|evil|DAN|jailbreak)", re.I
55 ),
56 re.compile(
57 r"you\s+are\s+now\s+(an?\s+)?(uncensored|unrestricted|DAN|evil\s+AI)", re.I
58 ),
59 re.compile(r"DAN\s+mode", re.I),
60 re.compile(r"jailbreak\s+(mode|prompt|yourself)", re.I),
61 re.compile(r"developer\s+mode\s+enabled", re.I),
62]
64# Exfiltration / system prompt extraction attempts
65_EXFILTRATION_PATTERNS: list[re.Pattern[str]] = [
66 re.compile(
67 r"(print|repeat|output|echo|reveal|show|tell\s+me|what\s+(are|is))\s+(your|the)\s+system\s+prompt",
68 re.I,
69 ),
70 re.compile(
71 r"(print|reveal|output|show|tell\s+me)\s+(your\s+)?(initial|original|base)\s+instructions?",
72 re.I,
73 ),
74 re.compile(
75 r"what\s+(instructions?|prompts?)\s+(were\s+you|have\s+you\s+been)\s+given",
76 re.I,
77 ),
78]
80_ALL_PATTERNS: list[tuple[str, list[re.Pattern[str]]]] = [
81 ("instruction_override", _OVERRIDE_PATTERNS),
82 ("roleplay_jailbreak", _ROLEPLAY_PATTERNS),
83 ("prompt_exfiltration", _EXFILTRATION_PATTERNS),
84]
87def _detect_injection(content: str) -> tuple[bool, str, str]:
88 """Check content for injection patterns.
90 Args:
91 content: Text to inspect.
93 Returns:
94 Tuple of (detected, category, matched_pattern_description).
95 """
96 for category, patterns in _ALL_PATTERNS:
97 for pattern in patterns:
98 match = pattern.search(content)
99 if match:
100 return True, category, match.group(0)[:80]
101 return False, "", ""
104class PromptInjectionDetector(AbstractInputGuard):
105 """Heuristic detector for prompt injection and jailbreak attempts.
107 Blocks or warns on content that attempts to override system
108 instructions, break out of a persona, or exfiltrate the system prompt.
110 Args:
111 action: Action when injection is detected — ``"block"`` (default)
112 or ``"warn"``.
114 Example::
116 guard = PromptInjectionDetector(action="block")
117 result = await guard.check(user_message)
118 if not result.passed:
119 return Err(InjectionAttemptError())
120 """
122 def __init__(self, action: str = "block") -> None:
123 """Initialise the injection detector.
125 Args:
126 action: ``"block"`` or ``"warn"``.
127 """
128 super().__init__(action=action)
130 async def check(
131 self,
132 content: str,
133 *,
134 messages: list[Any] | None = None,
135 metadata: dict[str, Any] | None = None,
136 ) -> Result[GuardResultProtocol, GuardError]:
137 """Evaluate content for prompt injection attempts.
139 Args:
140 content: User-supplied text to check.
141 messages: Optional structured messages for context.
142 metadata: Optional request metadata.
144 Returns:
145 BLOCK or WARN if injection detected, PASS otherwise.
146 """
147 detected, category, matched = _detect_injection(content)
149 if not detected:
150 return Ok(GuardCheckResult.allow(self.name))
152 if self._action == "warn":
153 return Ok(
154 GuardCheckResult.warn(
155 self.name,
156 reason=f"Potential prompt injection detected ({category})",
157 category=category,
158 matched_fragment=matched,
159 )
160 )
162 return Ok(
163 GuardCheckResult.block(
164 self.name,
165 reason=f"Prompt injection attempt detected ({category})",
166 category=category,
167 matched_fragment=matched,
168 )
169 )
172__all__ = ["PromptInjectionDetector"]