Spaces:
Runtime error
Runtime error
File size: 2,682 Bytes
24ea8aa | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | """
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):
@wraps(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
|