48 lines
2.2 KiB
Python
48 lines
2.2 KiB
Python
"""
|
|
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"
|