| 252 | ] |
| 253 | |
| 254 | def validate(self, user_input: str) -> ValidationResult: |
| 255 | if not user_input or not user_input.strip(): |
| 256 | return ValidationResult( |
| 257 | passed=False, |
| 258 | failure_mode=FailureMode.CONSTRAINT_VIOLATION, |
| 259 | message="Input is empty.", |
| 260 | score=0.0, |
| 261 | ) |
| 262 | |
| 263 | if len(user_input) > self.max_input_chars: |
| 264 | return ValidationResult( |
| 265 | passed=False, |
| 266 | failure_mode=FailureMode.TOKEN_OVERFLOW, |
| 267 | message=( |
| 268 | f"Input exceeds {self.max_input_chars} chars " |
| 269 | f"({len(user_input)} received)." |
| 270 | ), |
| 271 | score=0.0, |
| 272 | ) |
| 273 | |
| 274 | for pattern in self._patterns: |
| 275 | if pattern.search(user_input): |
| 276 | return ValidationResult( |
| 277 | passed=False, |
| 278 | failure_mode=FailureMode.PROMPT_INJECTION, |
| 279 | message=f"Injection pattern detected: '{pattern.pattern[:60]}'", |
| 280 | score=0.0, |
| 281 | ) |
| 282 | |
| 283 | return ValidationResult(passed=True, score=1.0) |
| 284 | |
| 285 | def sanitize(self, user_input: str) -> str: |
| 286 | text = user_input.strip() |