ForcePilot/backend/package/yuxi/channels/adapters/imessage/media_security.py
Kris 8f352d91bb feat(imessage): 新增投票管理、审计日志功能并优化多项细节
1. 新增poll命令支持创建、关闭、列出投票
2. 新增审计日志记录功能
3. 优化远程附件URL安全校验逻辑
4. 修复表格匹配正则,支持包含竖线的表格分隔行
5. 新增媒体AI处理能力,支持图片描述和音频转录
6. 完善配置校验和错误处理
7. 重构文本发送逻辑,增加重试机制
8. 新增投票投票处理逻辑,支持数字快捷投票
2026-05-13 16:10:03 +08:00

92 lines
2.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from __future__ import annotations
import os
from pathlib import Path
from yuxi.utils.logging_config import logger
DEFAULT_IMESSAGE_ATTACHMENT_ROOTS = [
"/Users/*/Library/Messages/Attachments",
]
def resolve_attachment_roots(
configured_roots: list[str] | None = None,
) -> list[str]:
if configured_roots:
return configured_roots
expanded: list[str] = []
for pattern in DEFAULT_IMESSAGE_ATTACHMENT_ROOTS:
import glob as _glob_module
matches = _glob_module.glob(pattern)
if matches:
expanded.extend(matches)
return expanded or DEFAULT_IMESSAGE_ATTACHMENT_ROOTS
def validate_attachment_path(
file_path: str,
allowed_roots: list[str] | None = None,
) -> bool:
"""校验附件路径是否在允许的根路径内。
阻止路径遍历攻击(如 ../../etc/passwd
"""
if not file_path:
return False
real_path = os.path.realpath(file_path) if os.path.exists(file_path) else os.path.abspath(file_path)
roots = allowed_roots or []
if not roots:
return True
for root in roots:
root_real = os.path.realpath(root) if os.path.exists(root) else os.path.abspath(root)
try:
Path(real_path).relative_to(root_real)
return True
except ValueError:
continue
logger.warning(f"[iMessage/Security] Attachment path rejected: {file_path} not in allowed roots")
return False
def validate_remote_attachment_url(
url: str,
allowed_roots: list[str] | None = None,
server_url: str = "",
) -> bool:
"""校验远程附件 URL 是否安全。"""
from urllib.parse import urlparse
if not url:
return False
parsed_url = urlparse(url)
url_host = parsed_url.hostname or ""
if allowed_roots:
for root in allowed_roots:
root_parsed = urlparse(root)
root_host = root_parsed.hostname or ""
if url_host == root_host and url.startswith(root):
return True
return False
if server_url and url.startswith(server_url):
return True
return False
def sanitize_attachment_filename(filename: str) -> str:
"""净化附件文件名,移除路径分隔符。"""
if not filename:
return "attachment"
basename = os.path.basename(filename)
safe = "".join(c for c in basename if c.isalnum() or c in "._-() ")
return safe or "attachment"