""" save_file 安全修复测试 ============================================================= 验证临时文件迁移的防护与正式路径保留: - FLASK_FILE_URL 为空时拒绝外链(原 find('')==0 恒真,外链被当本地文件) - URL 前缀不匹配时拒绝 - 路径穿越(.. 逃逸临时目录)拒绝 - 正式路径(不含 /temp)原样保留:相对路径(如 /images/notice/...)编辑回传 不被清空,带前缀的绝对地址只去前缀,外链绝对地址仍拒绝 """ from src.common.utils import rich_text def test_external_url_rejected_when_prefix_empty(monkeypatch): monkeypatch.setattr(rich_text, 'FLASK_FILE_URL', '') assert rich_text.save_file('http://evil.com/x.jpg', 'user') == "" def test_external_url_nonmatching_prefix_rejected(monkeypatch): monkeypatch.setattr(rich_text, 'FLASK_FILE_URL', 'http://img.site') assert rich_text.save_file('http://evil.com/x.jpg', 'user') == "" def test_path_traversal_rejected(monkeypatch): monkeypatch.setattr(rich_text, 'FLASK_FILE_URL', 'http://img.site') # realpath 规范化后逃逸临时目录 → 拒绝 assert rich_text.save_file('http://img.site/temp/../../../../../../etc/passwd', 'user') == "" def test_non_temp_url_returns_stripped_path(monkeypatch): monkeypatch.setattr(rich_text, 'FLASK_FILE_URL', 'http://img.site') # 已是正式路径(无 /temp)→ 去掉前缀返回,不迁移 assert rich_text.save_file('http://img.site/user/avatar.jpg', 'user') == "/user/avatar.jpg" def test_non_temp_relative_path_kept_when_prefix_mismatch(monkeypatch): monkeypatch.setattr(rich_text, 'FLASK_FILE_URL', 'http://img.site') # 编辑回传已保存的相对路径(如通知封面),前缀不匹配也应原样保留,不置空 assert rich_text.save_file('/images/notice/20260314/x.png', 'notice') == "/images/notice/20260314/x.png" def test_non_temp_relative_path_kept_when_prefix_empty(monkeypatch): monkeypatch.setattr(rich_text, 'FLASK_FILE_URL', '') # 未配置文件域名时,相对路径同样原样保留 assert rich_text.save_file('/notice/20260314/x.png', 'notice') == "/notice/20260314/x.png"