From 1839328dfecae27fee8b0a438f6026081d9cdb31 Mon Sep 17 00:00:00 2001 From: Florian Heinz Date: Fri, 5 Jun 2026 16:23:38 +0200 Subject: [PATCH] Harden local secrets and backup restore --- .dockerignore | 4 ++++ .gitignore | 1 + nouri.sqlite3 | 0 nouri/backup.py | 6 +++++- requirements.txt | 2 +- 5 files changed, 11 insertions(+), 2 deletions(-) delete mode 100644 nouri.sqlite3 diff --git a/.dockerignore b/.dockerignore index 2f95a59..ae71194 100644 --- a/.dockerignore +++ b/.dockerignore @@ -12,3 +12,7 @@ dist build data instance +.cloudron-push.env +.env.local +.env.push.local +nouri.sqlite3 diff --git a/.gitignore b/.gitignore index af73b91..6e87524 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ __pycache__/ data/ instance/ +nouri.sqlite3 .cloudron-push.env .env.local .env.push.local diff --git a/nouri.sqlite3 b/nouri.sqlite3 deleted file mode 100644 index e69de29..0000000 diff --git a/nouri/backup.py b/nouri/backup.py index 3c1b1fc..d9b83e2 100644 --- a/nouri/backup.py +++ b/nouri/backup.py @@ -77,6 +77,7 @@ def export_backup_archive( def _extract_uploads_to_temp(archive: zipfile.ZipFile) -> Path: temp_dir = Path(tempfile.mkdtemp(prefix="nouri-restore-uploads-")) + temp_root = temp_dir.resolve() for member in archive.infolist(): if not member.filename.startswith("uploads/") or member.is_dir(): continue @@ -84,8 +85,11 @@ def _extract_uploads_to_temp(archive: zipfile.ZipFile) -> Path: if not relative_target: continue target_path = temp_dir / relative_target + resolved_target = target_path.resolve() + if not resolved_target.is_relative_to(temp_root): + raise ValueError("Das Backup enthält einen ungültigen Upload-Pfad.") target_path.parent.mkdir(parents=True, exist_ok=True) - with archive.open(member, "r") as source, target_path.open("wb") as destination: + with archive.open(member, "r") as source, resolved_target.open("wb") as destination: shutil.copyfileobj(source, destination) return temp_dir diff --git a/requirements.txt b/requirements.txt index 34430bd..f5dfa58 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ Flask==3.1.1 gunicorn==23.0.0 pywebpush==2.3.0 -Pillow==11.2.1; python_version < "3.14" +Pillow==12.2.0; python_version < "3.14" fpdf2==2.8.3