"""data_convert 模块安全回归测试:输出文件名路径穿越与鉴权。 - ``output_filename`` 必须通过白名单校验,阻断 ``../``、``/``、``\\`` 及控制字符, 否则转换结果可被写出到存储根目录之外(任意文件读写/删除)。 - 所有 data_convert 路由必须挂载 ``get_current_user`` 鉴权依赖。 """ from __future__ import annotations import pytest from fastapi import HTTPException from app.core.auth import get_current_user from app.modules.data_convert.router import _safe_output_filename, router def test_safe_output_filename_defaults() -> None: assert _safe_output_filename(None) == "converted-data.jsonl" assert _safe_output_filename("") == "converted-data.jsonl" def test_safe_output_filename_valid() -> None: assert _safe_output_filename("converted-data.jsonl") == "converted-data.jsonl" assert _safe_output_filename("my-data.v1.jsonl") == "my-data.v1.jsonl" assert _safe_output_filename(" 报告.jsonl ") == "报告.jsonl" @pytest.mark.parametrize( "bad", [ "../../etc/passwd", "../x.jsonl", "a/b.jsonl", r"a\b.jsonl", "a\\b.jsonl", "..", ".", "x\x00.jsonl", "x\n.jsonl", "x\t.jsonl", ], ) def test_safe_output_filename_rejects_traversal(bad: str) -> None: with pytest.raises(HTTPException): _safe_output_filename(bad) def test_all_data_convert_routes_require_auth() -> None: for route in router.routes: node = getattr(route, "dependant", None) assert node is not None, f"route {route.path} has no dependency graph" stack = list(node.dependencies) calls: list = [] while stack: dep = stack.pop() stack.extend(getattr(dep, "dependencies", [])) calls.append(getattr(dep, "call", None)) assert get_current_user in calls, f"route {route.path} is missing get_current_user auth"