Merge commit from fork

file_id values from backup manifests are device controlled and were used
directly to construct host filesystem paths without validation, allowing
a malicious backup to read or write files outside the designated directories.

Validate each file_id with Path.resolve() + is_relative_to() before use
as a source or destination path. Unsafe entries are skipped and logged.

Fixes GHSA-5h3g-px23-w6vw
This commit is contained in:
tes
2026-05-12 12:17:48 -03:00
committed by GitHub
parent 436a0dc7c0
commit 2a3423d826
2 changed files with 10 additions and 0 deletions
+7
View File
@@ -11,6 +11,7 @@ import os
import os.path
import shutil
import sqlite3
from pathlib import Path
from typing import Optional
from iOSbackup import iOSbackup
@@ -96,6 +97,9 @@ class DecryptBackup:
# This may be a partial backup. Skip files from the manifest
# which do not exist locally.
source_file_path = os.path.join(self.backup_path, file_id[0:2], file_id)
if not Path(source_file_path).resolve().is_relative_to(Path(self.backup_path).resolve()):
log.warning("Skipping unsafe file_id: %r", file_id)
continue
if not os.path.exists(source_file_path):
log.debug(
"Skipping file %s. File not found in encrypted backup directory.",
@@ -104,6 +108,9 @@ class DecryptBackup:
continue
item_folder = os.path.join(self.dest_path, file_id[0:2]) # type: ignore[arg-type]
if not Path(os.path.join(item_folder, file_id)).resolve().is_relative_to(Path(self.dest_path).resolve()):
log.warning("Skipping unsafe file_id: %r", file_id)
continue
if not os.path.exists(item_folder):
os.makedirs(item_folder)
+3
View File
@@ -9,6 +9,7 @@ import os
import shutil
import sqlite3
import subprocess
from pathlib import Path
from typing import Iterator, Optional, Union
from mvt.common.module import (
@@ -165,6 +166,8 @@ class IOSExtraction(MVTModule):
if not self.target_path:
return None
file_path = os.path.join(self.target_path, file_id[0:2], file_id)
if not Path(file_path).resolve().is_relative_to(Path(self.target_path).resolve()):
return None
if os.path.exists(file_path):
return file_path