Spaces:
Sleeping
Sleeping
File size: 17,168 Bytes
840b896 |
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 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 |
import re
from typing import List, Tuple
import gradio as gr
class ContentSafetyChecker:
def __init__(self):
# Pre-compile regex patterns for performance
self.csam_patterns = self._compile_csam_patterns()
self.suspicious_combinations = self._compile_suspicious_combinations()
def _compile_csam_patterns(self) -> List[re.Pattern]:
"""Compile CSAM detection patterns"""
patterns = [
# Direct CSAM references
r'\b(csam|child.*sexual|minor.*abuse|illegal.*content)',
# Age + sexual content combinations
r'\b(child|kid|baby|toddler|infant|minor|youngster|youth|teen).*\b(sex|nude|naked|pussy|penis|vagina)',
r'\b(sex|nude|naked|porn|erotic|seductive|lust|breast|genital|penis|vagina).*\b(child|kid|baby|toddler|infant|minor|youngster|youth|teen)',
# Numerical age checks with sexual content
r'\b(?:age|aged?|years? old)\s*[=\-:]\s*(?:[0-9]|1[0-7])\b.*\b(sex|nude|naked|porn|erotic)',
r'\b([0-9]|1[0-7])\s*(?:years? old|yo|y/o)\b.*\b(sex|nude|naked|porn|erotic)',
# Numbers 3-17 directly followed by sexual content terms
r'\b([3-9]|1[0-7])\s*[,\-]?\s*(sex|nude|naked|porn|erotic|seductive|explicit)',
# Descriptive numerical age checks
r'\b(under\s*(1[0-8]|[0-9])|below\s*(1[0-8]|[0-9])|less than\s*(1[0-8]|[0-9]))\s*years?\s*[,\-]?\s*(sex|nude|naked|porn|erotic)',
# Inappropriate scenarios with numerical ages
r'\b(pedophil|lolita|underage.*sex|minor.*sex|illegal.*sex)',
# Grooming language
r'\b(inappropriate.*adult.*child|adult.*minor.*relationship|groom)',
]
return [re.compile(pattern, re.IGNORECASE) for pattern in patterns]
def _compile_suspicious_combinations(self) -> List[Tuple[List[str], List[str], int]]:
"""Define suspicious word combinations with numerical thresholds"""
return [
# Age indicators + sexual content ( Fixed tuple structure and removed extra parameters)
(['4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'young teen', 'minor', 'child', 'kid', 'baby'],
['nude', 'naked', 'sex', 'porn', 'erotic', 'seductive', 'penis', 'vagina', 'penetration', 'cock', 'pussy'], 8),
(['adult'],
['pedo', 'loli', 'secret', 'rape'], 5),
]
def check_pattern_matching(self, prompt: str) -> bool:
"""First line of defense: regex pattern matching"""
for pattern in self.csam_patterns:
if pattern.search(prompt):
print(f"🚨 Pattern matched: {pattern.pattern}")
return True
return False
def check_numerical_age_context(self, prompt: str) -> bool:
"""Check for numerical ages in suspicious contexts"""
prompt_lower = prompt.lower()
# Extract all numbers from prompt
numbers = re.findall(r'\b\d+\b', prompt_lower)
# Suspicious sexual content terms
sexual_terms = ['nude', 'naked', 'sex', 'porn', 'erotic', 'seductive', 'explicit', 'undress', 'penis', 'vagina', 'pussy', 'cock']
# Check each number
for num_str in numbers:
try:
age = int(num_str)
# If age is in minor range (3-17) and sexual content is mentioned
if 3 <= age <= 17 and any(term in prompt_lower for term in sexual_terms):
print(f"🚨 Suspicious age with sexual content: {age}")
return True
# Also check for descriptive phrases like "12 year old"
age_phrases = [
f"{num_str} year old",
f"{num_str} years old",
f"{num_str}yo",
f"{num_str} y/o"
]
if any(phrase in prompt_lower for phrase in age_phrases):
if 3 <= age <= 17 and any(term in prompt_lower for term in sexual_terms):
print(f"🚨 Suspicious age phrase with sexual content: {age}")
return True
except ValueError:
continue
# Check for phrases like "under 18", "below 16", etc.
age_limit_phrases = [
r'\bunder\s*(1[0-8]|[0-9])\b',
r'\bbelow\s*(1[0-8]|[0-9])\b',
r'\bless than\s*(1[0-8]|[0-9])\b',
r'\b[0-9]{1,2}\s*and under\b'
]
for phrase_pattern in age_limit_phrases:
if re.search(phrase_pattern, prompt_lower):
# Check if followed by sexual content within reasonable distance
match = re.search(phrase_pattern, prompt_lower)
phrase_end = match.end()
remaining_text = prompt_lower[phrase_end:]
if any(term in remaining_text for term in sexual_terms):
print(f"🚨 Age limit phrase with sexual content: {match.group()}")
return True
return False
def check_age_sexual_combinations(self, prompt: str) -> bool:
"""More sophisticated check for age terms combined with sexual content"""
prompt_lower = prompt.lower()
# Check age + sexual content with numerical extraction
age_sexual_patterns = [
r'(child|kid|baby|toddler|infant|minor|youngster|teen|youth)\s*(?:of|is|was)?\s*(\d{1,2})\s*(years?\s*old)?',
r'(\d{1,2})\s*(years?\s*old|yo|y/o)?\s*(child|kid|baby|toddler|infant|minor|young)',
]
sexual_content_patterns = ['nude', 'naked', 'sex', 'porn', 'erotic', 'explicit', 'sexual', 'penis', 'vagina', 'pussy', 'cock']
for age_pattern in age_sexual_patterns:
age_matches = re.finditer(age_pattern, prompt_lower)
for match in age_matches:
# Extract age number from match groups
age = None
for group in match.groups():
if group and group.isdigit():
age = int(group)
break
if age is not None and 3 <= age <= 17: # Minor age range
# Look for sexual content nearby (within 50 characters)
start_pos = max(0, match.start() - 50)
end_pos = min(len(prompt_lower), match.end() + 50)
context = prompt_lower[start_pos:end_pos]
if any(term in context for term in sexual_content_patterns):
print(f"🚨 Age-sexual content combination detected: age {age}")
return True
return False
def check_word_proximity(self, prompt: str) -> bool: # Removed unused max_distance parameter
"""Second line: check proximity of suspicious words including numerical checks"""
words = prompt.lower().split()
# Original non-numerical proximity checks
for age_words, sexual_words, distance_threshold in self.suspicious_combinations:
for age_word in age_words:
for sexual_word in sexual_words:
if age_word in words and sexual_word in words:
try:
age_idx = words.index(age_word)
sexual_idx = words.index(sexual_word)
if abs(age_idx - sexual_idx) <= distance_threshold:
return True
except ValueError:
continue
return False
def simple_age_check(self, prompt: str) -> bool: # Added self parameter
"""Simple numerical age check"""
numbers = re.findall(r'\b\d+\b', prompt)
sexual_terms = ['nude', 'naked', 'sex', 'porn', 'erotic', 'seductive', 'explicit', 'penis', 'vagina', 'pussy', 'cock']
for num in numbers:
try:
age = int(num)
if 3 <= age <= 17 and any(term in prompt.lower() for term in sexual_terms):
return True
except ValueError:
continue
return False
def check_suspicious_phrases(self, prompt: str) -> bool:
"""Third line: check for specific suspicious phrases"""
suspicious_phrases = [
'young model', 'teen photoshoot', 'minor content',
'child art', 'kids only', 'no adults allowed',
'private session', 'secret photos', 'hidden content'
]
prompt_lower = prompt.lower()
for phrase in suspicious_phrases:
if phrase in prompt_lower:
return True
return False
def check_evasion_patterns(self, prompt: str) -> bool:
"""Fourth line: check for common evasion techniques"""
# Look for character substitutions or obfuscation
evasion_indicators = [
r'p\w*is',
r'p\w*sy',
r's\w*x',
r'n\w*d\w*',
]
for pattern in evasion_indicators:
if re.search(pattern, prompt, re.IGNORECASE):
# Additional check: see if it's combined with age-related terms
age_indicators = ['old', 'teen', 'baby', 'kid', 'child', 'minor', 'young']
if any(indicator in prompt.lower() for indicator in age_indicators):
return True
return False
def check_numerical_age_indicators(self, prompt: str) -> bool:
"""Fifth line: check for specific age numbers with sexual content"""
# Extract numbers from prompt
numbers = re.findall(r'\b\d+\b', prompt)
sexual_indicators = ['nude', 'naked', 'sex', 'porn', 'erotic', 'nudify', 'off', 'penis', 'cock', 'pussy', 'vagina', 'insert']
for num_str in numbers:
try:
age = int(num_str)
# Flag ages typically associated with minors when combined with sexual content
if 3 <= age <= 17:
prompt_lower = prompt.lower()
if any(indicator in prompt_lower for indicator in sexual_indicators):
return True
except ValueError:
continue
return False
def check_contextual_red_flags(self, prompt: str) -> bool:
"""Sixth line: check for contextual red flags"""
red_flag_contexts = [
# Suspicious session types
(r'(private|secret|hidden|exclusive).*photo', ['nude', 'naked', 'photos']), # Fixed this tuple (was missing opening parenthesis)
# Suspicious content descriptions
(r'(special|unique|exclusive|view|angle|pov|shot).*content', ['young', 'minor', 'teen'])
]
prompt_lower = prompt.lower()
for context_pattern, suspicious_words in red_flag_contexts:
if re.search(context_pattern, prompt_lower):
if any(word in prompt_lower for word in suspicious_words):
return True
return False
def is_content_suspicious(self, prompt: str) -> Tuple[bool, str]:
"""Main safety checking function with detailed feedback"""
checks = [
(self.check_pattern_matching, "Pattern matching detected suspicious content"),
(self.check_word_proximity, "Suspicious word proximity detected"),
(self.check_suspicious_phrases, "Suspicious phrases detected"),
(self.check_evasion_patterns, "Potential evasion patterns detected"),
(self.check_numerical_age_indicators, "Suspicious age indicators with sexual content"),
(self.check_contextual_red_flags, "Contextual red flags detected"),
(self.simple_age_check, "Simple age check detected suspicious content"), # Added the missing simple_age_check
(self.check_numerical_age_context, "Numerical age context check detected suspicious content"), # Added numerical age context check
(self.check_age_sexual_combinations, "Age-sexual combination check detected suspicious content") # Added age-sexual combination check
]
for check_func, message in checks:
try:
if check_func(prompt):
return True, message
except Exception as e:
print(f"Warning: Safety check {check_func.__name__} failed: {e}")
continue
return False, "Content appears safe"
# Enhanced safety function
def comprehensive_safety_check(prompt: str) -> Tuple[bool, str]:
"""Multi-layer safety checking with fallback mechanisms"""
try:
# Initialize the safety checker for each check (ensures fresh state)
safety_checker = ContentSafetyChecker()
# Primary check
is_suspicious, message = safety_checker.is_content_suspicious(prompt)
if is_suspicious:
return True, message
# Fallback checks if primary fails
fallback_checks = [
lambda p: len(p) > 1000, # Unusually long prompts (potential obfuscation)
lambda p: p.count('"') > 20, # Excessive quotes (potential code injection)
lambda p: '||' in p or '&&' in p, # Shell command operators
lambda p: any(char in p for char in ['<script', 'javascript:', 'onload=']), # Basic XSS
]
for i, check in enumerate(fallback_checks):
try:
if check(prompt):
return True, f"Fallback safety check #{i+1} triggered"
except Exception:
continue
return False, "All safety checks passed"
except Exception as e:
print(f"Safety check failed, erring on caution: {e}")
return True, "Safety system error - content blocked for caution"
# Usage in your application
def test_prompt(original_prompt: str) -> str:
is_blocked, reason = comprehensive_safety_check(original_prompt)
if is_blocked:
print(f"🚨 SAFETY BLOCK: {reason} - Prompt: {original_prompt[:100]}...")
# Log the blocked content (for monitoring)
try:
with open("safety_blocks.log", "a") as f:
f.write(f"{reason}: {original_prompt}\n")
except Exception:
print("Warning: Could not write to safety log")
return "A professional and appropriate image editing task" # Safe fallback
# If safe, proceed with normal enhancement
return f"Regex safety check passed: {original_prompt}"
import gradio as gr
with gr.Blocks(title="Content Safety Checker | Testing Zone") as demo:
gr.Markdown("""
# 🛡️ Regex-based Content Safety Checker
Some of you guys need to seek help...
""")
with gr.Row():
with gr.Column(scale=1):
input_prompt = gr.Textbox(
label="Test Prompt",
placeholder="Type a prompt to check for safety...",
lines=5,
max_lines=10
)
check_button = gr.Button("Check Safety", variant="primary")
clear_button = gr.Button("Clear", variant="secondary")
with gr.Column(scale=2):
output_result = gr.Textbox(
label="Safety Check Result",
interactive=False,
lines=10,
max_lines=15
)
safety_info = gr.HTML(
value="<div style='padding:15px; margin-top:15px; background: #f8f9fa; border-radius: 8px;'>"
"<h4>ℹ️ How it works:</h4>"
"<ul>"
"<li>Multi-layer safety checking system</li>"
"<li>Detects age-related terms combined with sexual content</li>"
"<li>Identifies potential CSAM/illegal content patterns</li>"
"<li>Checks for evasion techniques and suspicious combinations</li>"
"</ul>"
"</div>"
)
def process_prompt(prompt):
if not prompt or not prompt.strip():
return "Please enter a prompt to test."
is_blocked, reason = comprehensive_safety_check(prompt)
if is_blocked:
return f"🚨 BLOCKED: {reason}\n\nOriginal prompt: {prompt}"
else:
return f"✅ SAFE: {reason}\n\nOriginal prompt: {prompt}"
def clear_inputs():
return "", ""
check_button.click(
fn=process_prompt,
inputs=input_prompt,
outputs=output_result
)
input_prompt.submit(
fn=process_prompt,
inputs=input_prompt,
outputs=output_result
)
clear_button.click(
fn=clear_inputs,
inputs=None,
outputs=[input_prompt, output_result]
)
demo.launch() |