objectif
Vérifier les chemins avant extraction d’une archive zip/tar.
code minimal
from zipfile import ZipFile
from pathlib import Path
from tempfile import TemporaryDirectory
def is_within_directory(base: Path, target: Path) -> bool:
try:
base_resolved = base.resolve(strict=False)
target_resolved = target.resolve(strict=False)
return str(target_resolved).startswith(str(base_resolved) + "/")
except Exception:
return False
def safe_extract_zip(zip_path: Path, dest: Path):
with ZipFile(zip_path) as z:
for m in z.infolist():
out_path = dest / m.filename
if not is_within_directory(dest, out_path):
raise ValueError("path traversal détecté")
z.extractall(dest)
with TemporaryDirectory() as tmp:
root = Path(tmp)
zpath = root / "t.zip"
with ZipFile(zpath, "w") as z:
z.writestr("ok.txt", "OK")
z.writestr("../evil.txt", "nope")
try:
safe_extract_zip(zpath, root / "out")
except ValueError:
print(True) # attendu: True (bloqué)
utilisation
print(True)
variante(s) utile(s)
# Variante tar: parcourir getmembers() et vérifier les noms
print(True)
notes
- Toujours valider les chemins d’archive avant extraction.
- Refusez les chemins absolus et ceux contenant ”..”.