1111from markupsafe import escape
1212from typing import Any , Dict , List , Optional , Union
1313import bleach
14+ import unicodedata
15+
16+
1417
1518logger = logging .getLogger (__name__ )
1619
20+ def normalize_unicode (text : str ) -> str :
21+ """Strip homoglyph and invisible control characters."""
22+ text = unicodedata .normalize ("NFC" , text )
23+ return "" .join (c for c in text if unicodedata .category (c ) not in ("Cc" , "Cf" ))
24+
1725# Patterns for potential prompt injection or malicious commands
1826PROMPT_INJECTION_PATTERNS = [
1927 r"(?i)ignore\s+all\s+previous\s+instructions" ,
@@ -72,6 +80,8 @@ def sanitize_string(text: Optional[str], max_len: int = 5000, strip_html: bool =
7280
7381 # Convert to string
7482 text = str (text ).strip ()
83+ text = normalize_unicode (text )
84+
7585
7686 if not text :
7787 return ""
@@ -115,8 +125,7 @@ def sanitize_string(text: Optional[str], max_len: int = 5000, strip_html: bool =
115125 strip = False # Convert unknown tags to entities
116126 )
117127
118- # Layer 3: Additional HTML escaping for extra safety
119- text = html .escape (text )
128+
120129
121130 # Layer 4: Limit length
122131 if len (text ) > max_len :
@@ -158,8 +167,7 @@ def sanitize_for_ai(text: Optional[str]) -> str:
158167 logger .warning (f"Possible prompt injection detected: { detected_patterns [:2 ]} " )
159168 clean_text = f"[User Input - Content Flagged]: { clean_text } "
160169
161- return clean_text
162-
170+ return f"<user_input>{ clean_text } </user_input>"
163171
164172
165173def sanitize_payload (data : Union [Dict , List , str , Any ]) -> Any :
@@ -179,7 +187,7 @@ def sanitize_payload(data: Union[Dict, List, str, Any]) -> Any:
179187 Sanitized version of the payload
180188 """
181189 if isinstance (data , dict ):
182- return {k : sanitize_payload (v ) for k , v in data .items ()}
190+ return {sanitize_string ( str ( k )) : sanitize_payload (v ) for k , v in data .items ()}
183191 elif isinstance (data , list ):
184192 return [sanitize_payload (i ) for i in data ]
185193 elif isinstance (data , str ):
0 commit comments