51 lines
1.7 KiB
Python
51 lines
1.7 KiB
Python
"""Тесты безопасности routes/upload_bp.py — чистые функции, без HTTP."""
|
|
import io
|
|
import zipfile
|
|
|
|
from routes.upload_bp import _check_ext, _unzip
|
|
|
|
|
|
class TestCheckExt:
|
|
def test_allowed(self):
|
|
assert _check_ext("a.pdf") is None
|
|
assert _check_ext("a.docx") is None
|
|
assert _check_ext("a.doc") is None
|
|
assert _check_ext("a.zip") is None
|
|
|
|
def test_rejected(self):
|
|
assert _check_ext("a.exe") is not None
|
|
assert _check_ext("a.txt") is not None
|
|
assert _check_ext("noext") is not None
|
|
|
|
def test_uppercase(self):
|
|
assert _check_ext("A.PDF") is None
|
|
|
|
|
|
class TestUnzip:
|
|
def _zip(self, entries):
|
|
buf = io.BytesIO()
|
|
with zipfile.ZipFile(buf, "w") as zf:
|
|
for name, content in entries.items():
|
|
zf.writestr(name, content)
|
|
return buf.getvalue()
|
|
|
|
def test_valid(self):
|
|
ok, files, err = _unzip(self._zip({"a.docx": b"hello", "b.pdf": b"world"}))
|
|
assert ok is True
|
|
assert len(files) == 2
|
|
assert files[0]["filename"] == "a.docx"
|
|
assert files[0]["data_b64"]
|
|
|
|
def test_path_traversal_neutralized(self):
|
|
ok, files, err = _unzip(self._zip({"../etc/passwd": b"evil"}))
|
|
assert ok is True
|
|
# basename убирает каталог — имя файла не содержит путь
|
|
assert files[0]["filename"] == "passwd"
|
|
assert ".." not in files[0]["filename"]
|
|
assert "/" not in files[0]["filename"]
|
|
|
|
def test_invalid_zip(self):
|
|
ok, files, err = _unzip(b"not a zip at all")
|
|
assert ok is False
|
|
assert err == "invalid ZIP archive"
|