Spaces:
Runtime error
Runtime error
| """ | |
| Input validation utilities for audio uploads and text sanitization. | |
| """ | |
| import re | |
| import logging | |
| from functools import wraps | |
| from flask import request, jsonify | |
| logger = logging.getLogger(__name__) | |
| # Patterns commonly used in prompt injection attempts | |
| _INJECTION_PATTERNS = [ | |
| re.compile(r'ignore\s+(all\s+)?previous\s+instructions', re.IGNORECASE), | |
| re.compile(r'ignore\s+(all\s+)?above\s+instructions', re.IGNORECASE), | |
| re.compile(r'^system\s*:', re.IGNORECASE | re.MULTILINE), | |
| re.compile(r'you\s+are\s+now\s+(?:a|an|the)\s+', re.IGNORECASE), | |
| re.compile(r'pretend\s+(?:you\s+are|to\s+be)', re.IGNORECASE), | |
| re.compile(r'act\s+as\s+(?:a|an|if)', re.IGNORECASE), | |
| re.compile(r'new\s+instructions?\s*:', re.IGNORECASE), | |
| re.compile(r'disregard\s+(?:all\s+)?(?:previous|prior|above)', re.IGNORECASE), | |
| ] | |
| def validate_audio_upload(field_name='audio'): | |
| """Decorator to validate audio file uploads. | |
| Checks that a file is present, not empty, and within size limits. | |
| Returns 400 JSON on validation failure. | |
| """ | |
| def decorator(f): | |
| def wrapper(*args, **kwargs): | |
| if request.method == 'OPTIONS': | |
| return f(*args, **kwargs) | |
| if field_name not in request.files: | |
| return jsonify({'success': False, 'error': f'No {field_name} file provided'}), 400 | |
| audio_file = request.files[field_name] | |
| if not audio_file.filename: | |
| return jsonify({'success': False, 'error': 'Empty filename'}), 400 | |
| # Check file size (read content length from stream) | |
| audio_file.seek(0, 2) # seek to end | |
| file_size = audio_file.tell() | |
| audio_file.seek(0) # reset to beginning | |
| if file_size < 100: | |
| return jsonify({'success': False, 'error': 'Audio file too small (possibly empty recording)'}), 400 | |
| if file_size > 30 * 1024 * 1024: # 30MB | |
| return jsonify({'success': False, 'error': 'Audio file too large. Maximum size is 30MB.'}), 400 | |
| return f(*args, **kwargs) | |
| return wrapper | |
| return decorator | |
| def sanitize_text_for_llm(text, max_length=5000): | |
| """Sanitize user-provided text before passing to LLM. | |
| Truncates to max_length and strips common prompt injection patterns. | |
| """ | |
| if not text: | |
| return '' | |
| # Truncate | |
| text = text[:max_length] | |
| # Strip injection patterns | |
| for pattern in _INJECTION_PATTERNS: | |
| text = pattern.sub('', text) | |
| # Remove excessive whitespace that could result from stripping | |
| text = re.sub(r'\n{3,}', '\n\n', text) | |
| text = text.strip() | |
| return text | |