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:
commit
38822f7871
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user