mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-07-09 03:04:54 -04:00
security: restrict backup file upload (#1522)
This commit is contained in:
parent
6649ccf224
commit
11478134a1
@ -72,13 +72,24 @@ class AdminBackupController(BaseAdminController):
|
|||||||
@router.post("/upload", response_model=SuccessResponse)
|
@router.post("/upload", response_model=SuccessResponse)
|
||||||
def upload_one(self, archive: UploadFile = File(...)):
|
def upload_one(self, archive: UploadFile = File(...)):
|
||||||
"""Upload a .zip File to later be imported into Mealie"""
|
"""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()
|
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:
|
with dest.open("wb") as buffer:
|
||||||
shutil.copyfileobj(archive.file, buffer)
|
shutil.copyfileobj(archive.file, buffer)
|
||||||
|
|
||||||
if not dest.is_file:
|
if not dest.is_file():
|
||||||
raise HTTPException(status.HTTP_400_BAD_REQUEST)
|
raise HTTPException(status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
@router.post("/{file_name}/restore", response_model=SuccessResponse)
|
@router.post("/{file_name}/restore", response_model=SuccessResponse)
|
||||||
|
25
tests/integration_tests/admin_tests/test_admin_backup.py
Normal file
25
tests/integration_tests/admin_tests/test_admin_backup.py
Normal file
@ -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()
|
Loading…
x
Reference in New Issue
Block a user