"""Security tests for backup/restore endpoints (e2e — uses live app).""" import io import zipfile from tests.e2e.conftest import API_KEY # type: ignore def test_restore_rejects_path_traversal_zip(client): """ZIP entries with ../ must be rejected.""" buf = io.BytesIO() with zipfile.ZipFile(buf, "w") as zf: zf.writestr( "ledgrab.db", b"SQLite format 3\x00" + b"\x00" * 200, ) zf.writestr("assets/../evil.txt", b"bad") buf.seek(0) resp = client.post( "/api/v1/system/restore", files={"file": ("backup.zip", buf.getvalue(), "application/zip")}, ) assert resp.status_code == 400 assert "traversal" in resp.text.lower() def test_backup_download_requires_non_anonymous(client): """Backup download rejects anonymous (loopback) callers.""" import ledgrab.config as cm from ledgrab.config import AuthConfig saved = cm.config cm.config = saved.model_copy(update={"auth": AuthConfig(api_keys={})}) try: client.headers.pop("Authorization", None) resp = client.get("/api/v1/system/backup") assert resp.status_code == 401 finally: cm.config = saved client.headers["Authorization"] = f"Bearer {API_KEY}" def test_backup_roundtrip_authenticated(client): """A normal authenticated download still works.""" resp = client.get("/api/v1/system/backup") assert resp.status_code == 200 assert resp.headers["content-type"] == "application/zip" assert resp.content[:4] == b"PK\x03\x04"