latentlearn-agent / utils /security.py
howcloudy's picture
Deploy LatentLearn Python Agent Backend to Hugging Face Space
89d813f
Raw
History Blame Contribute Delete
4.96 kB
"""
utils/security.py — LatentLearn 多维安全防护与敏感拦截层
功能:
1. HTML 标签剥离(防止 XSS 脚本跨站攻击和注入污染)
2. 递归清洗上传文档(防止注入文本对大模型及前端组件造成危害)
3. 用户提问长度限制(防御 DoS 与 Token 爆满)
4. 提示词注入拦截(秒级拦截绕过指令)
5. 核心有毒/违规内容拦截(自残自杀、毒品枪支、网络诈骗、洗钱等)
"""
from __future__ import annotations
import re
# 1. 提示词注入攻击正则检测 (Prompt Injection Detection Patterns)
_INJECTION_PATTERNS = [
r"ignore\s+(?:the\s+)?(?:previous|system|prior)\s+(?:instruction|prompt|rule|message|setting|directive)",
r"forget\s+(?:the\s+)?(?:previous|system|prior)\s+(?:instruction|prompt|rule|message|setting|directive)",
r"you\s+must\s+now\s+act\s+as",
r"you\s+are\s+now\s+a\s+",
r"bypass\s+(?:the\s+)?(?:system|security|filter|guardrail)",
r"忽略(?:之前|先前的?)(?:指令|提示|规则|设定|说明|约束)",
r"忘记(?:之前|先前的?)(?:指令|提示|规则|设定|说明|约束)",
r"你现在(是|扮演|开始充当)\s*",
r"解除(?:系统|安全)?限制",
r"绕过(?:安全|系统|过滤)?",
r"print\s+(?:your\s+)?system\s+(?:prompt|message|instruction)",
r"输出(?:你?的?)?系统(?:提示词|指令|初始设置)"
]
# 2. 政治/黄暴/自残敏感词本地正则过滤 (Mild local keyword blacklist for toxic/illegal/self-harm queries)
_TOXIC_PATTERNS = [
r"(?:自杀|自残|割腕|服毒|跳楼|不想活了|suicide|self-harm|kill\s+myself|end\s+my\s+life)",
r"(?:吸毒|冰毒|海洛因|贩毒|大麻|meth|heroin|marijuana|drug\s+deal)",
r"(?:制作炸弹|枪支制造|制造枪支|bomb\s+making|make\s+a\s+bomb|weapons\s+manufacturing)",
r"(?:洗钱|诈骗|传销|money\s+laundering|scam|pyramid\s+scheme)"
]
# 3. HTML 标签剥离正则 (XSS Sanitizer)
_HTML_TAG_PATTERN = re.compile(r"<[^>]+>")
def sanitize_text(text: str | None) -> str | None:
"""过滤 HTML 标签以防止 XSS 攻击,保证文本纯净"""
if not text:
return text
# 剥离所有 HTML 标签,只保留纯文本
return _HTML_TAG_PATTERN.sub("", text).strip()
def sanitize_document(document: dict | None) -> dict | None:
"""
递归清洗上传的学习文档:
- 清洗标题 (title)
- 清洗大章节正文 (content)
- 递归清洗大纲小节结构 (structure)
返回清洗后 100% 纯净、无 script/HTML 注入的安全文档字典。
"""
if not document:
return document
sanitized = dict(document)
if "title" in sanitized and isinstance(sanitized["title"], str):
sanitized["title"] = sanitize_text(sanitized["title"])
if "content" in sanitized and isinstance(sanitized["content"], str):
sanitized["content"] = sanitize_text(sanitized["content"])
if "structure" in sanitized and isinstance(sanitized["structure"], list):
new_struct = []
for sec in sanitized["structure"]:
if isinstance(sec, dict):
new_sec = dict(sec)
if "title" in new_sec and isinstance(new_sec["title"], str):
new_sec["title"] = sanitize_text(new_sec["title"])
if "content" in new_sec and isinstance(new_sec["content"], str):
new_sec["content"] = sanitize_text(new_sec["content"])
new_struct.append(new_sec)
sanitized["structure"] = new_struct
return sanitized
def check_query_safety(query: str | None) -> tuple[bool, str | None]:
"""
检查用户输入的安全健康状况。
返回: (is_safe, error_hint)
"""
if not query:
return True, None
# A. 限制输入长度,防止拒绝服务(DoS)或 Token 爆满
if len(query) > 1000:
return False, "Input query is too long (maximum 1000 characters). / 输入提问过长(最多支持 1000 字)。"
# B. 过滤 HTML 注入 / XSS 并校验清洗后字符
sanitized = sanitize_text(query)
if not sanitized or not sanitized.strip():
return False, "Input query is empty after sanitization. / 输入文本清洗后为空,请不要注入无效 HTML 代码。"
# C. 提示词注入检测
for pattern in _INJECTION_PATTERNS:
if re.search(pattern, sanitized, re.IGNORECASE):
return False, "Security Alert: Prompt injection attempt detected. Please stay on study focus. / 安全警告:检测到提示词指令注入,请专注于学术和文档阅读辅导。"
# D. 敏感/有毒内容拦截
for pattern in _TOXIC_PATTERNS:
if re.search(pattern, sanitized, re.IGNORECASE):
return False, "Safety Alert: Content violates safety guidelines. / 安全提示:提问涉及高风险或有害主题,已被系统自动拦截。"
return True, None