diff --git a/mealie/routes/admin/admin_backups.py b/mealie/routes/admin/admin_backups.py index aa3a567075ae..7b33cbf6f246 100644 --- a/mealie/routes/admin/admin_backups.py +++ b/mealie/routes/admin/admin_backups.py @@ -72,13 +72,24 @@ class AdminBackupController(BaseAdminController): @router.post("/upload", response_model=SuccessResponse) def upload_one(self, archive: UploadFile = File(...)): """Upload a .zip File to later be imported into Mealie""" + if "." not in archive.filename: + raise HTTPException(status.HTTP_400_BAD_REQUEST) + + if archive.filename.split(".")[-1] != "zip": + raise HTTPException(status.HTTP_400_BAD_REQUEST) + + name = Path(archive.filename).stem + app_dirs = get_app_dirs() - dest = app_dirs.BACKUP_DIR.joinpath(archive.filename) + dest = app_dirs.BACKUP_DIR.joinpath(f"{name}.zip") + + if dest.absolute().parent != app_dirs.BACKUP_DIR: + raise HTTPException(status.HTTP_400_BAD_REQUEST) with dest.open("wb") as buffer: shutil.copyfileobj(archive.file, buffer) - if not dest.is_file: + if not dest.is_file(): raise HTTPException(status.HTTP_400_BAD_REQUEST) @router.post("/{file_name}/restore", response_model=SuccessResponse) diff --git a/tests/integration_tests/admin_tests/test_admin_backup.py b/tests/integration_tests/admin_tests/test_admin_backup.py new file mode 100644 index 000000000000..c29afa8c2be5 --- /dev/null +++ b/tests/integration_tests/admin_tests/test_admin_backup.py @@ -0,0 +1,25 @@ +from fastapi.testclient import TestClient + +from mealie.core.config import get_app_dirs +from tests import data +from tests.utils.fixture_schemas import TestUser + + +def test_recipe_asset_exploit(api_client: TestClient, admin_user: TestUser): + dirs = get_app_dirs() + + file_payload = { + "archive": ("../test.txt", data.images_test_image_1.read_bytes()), + } + + response = api_client.post( + "/api/admin/backups/upload", + files=file_payload, + headers=admin_user.token, + ) + + assert response.status_code == 400 + + # Ensure File was not created + assert not (dirs.BACKUP_DIR / "test.txt").exists() + assert not (dirs.BACKUP_DIR.parent / "test.txt").exists()