test: набор pytest-тестов под site/ (unit + интеграционные + безопасность)
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
"""Тесты безопасности 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"
|
||||
Reference in New Issue
Block a user