2
0
mirror of https://github.com/frappe/bench.git synced 2024-09-27 22:39:03 +00:00

Merge pull request #1523 from frappe/add-tar-safety

fix: add safety filter for untarring
This commit is contained in:
Alan 2024-01-24 12:22:12 +05:30 committed by GitHub
commit 38822f7871
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 40 additions and 1 deletions

View File

@ -24,6 +24,7 @@ from bench.exceptions import NotInBenchDirectoryError
from bench.utils import ( from bench.utils import (
UNSET_ARG, UNSET_ARG,
fetch_details_from_tag, fetch_details_from_tag,
get_app_cache_extract_filter,
get_available_folder_name, get_available_folder_name,
get_bench_cache_path, get_bench_cache_path,
is_bench_directory, is_bench_directory,
@ -343,7 +344,12 @@ class App(AppMeta):
click.secho(f"Getting {self.app_name} from cache", fg="yellow") click.secho(f"Getting {self.app_name} from cache", fg="yellow")
with tarfile.open(cache_path, mode) as tar: with tarfile.open(cache_path, mode) as tar:
tar.extractall(app_path.parent) try:
tar.extractall(app_path.parent, filter=get_app_cache_extract_filter())
except Exception:
logger.exception(f"Cache extraction failed for {self.app_name}")
shutil.rmtree(app_path)
return False
return True return True

View File

@ -9,6 +9,7 @@ from functools import lru_cache
from glob import glob from glob import glob
from pathlib import Path from pathlib import Path
from shlex import split from shlex import split
from tarfile import TarInfo
from typing import List, Optional, Tuple from typing import List, Optional, Tuple
# imports - third party imports # imports - third party imports
@ -569,3 +570,35 @@ def get_cmd_from_sysargv():
break break
return cmd_from_ctx return cmd_from_ctx
def get_app_cache_extract_filter(
count_threshold: int = 10_000,
size_threshold: int = 1_000_000_000,
): # -> Callable[[TarInfo, str], TarInfo | None]
state = dict(count=0, size=0)
AbsoluteLinkError = Exception
def data_filter(m: TarInfo, _:str) -> TarInfo:
return m
if (sys.version_info.major == 3 and sys.version_info.minor > 7) or sys.version_info.major > 3:
from tarfile import data_filter, AbsoluteLinkError
def filter_function(member: TarInfo, dest_path: str) -> Optional[TarInfo]:
state["count"] += 1
state["size"] += member.size
if state["count"] > count_threshold:
raise RuntimeError(f"Number of entries exceeds threshold ({state['count']})")
if state["size"] > size_threshold:
raise RuntimeError(f"Extracted size exceeds threshold ({state['size']})")
try:
return data_filter(member, dest_path)
except AbsoluteLinkError:
# Links created by `frappe` after extraction
return None
return filter_function