This is an automated email from the ASF dual-hosted git repository. sbp pushed a commit to branch sbp in repository https://gitbox.apache.org/repos/asf/tooling-trusted-releases.git
commit 93e40f1c2c9275b2f32d1d5835b5fbf0a5b7bef7 Author: Sean B. Palmer <[email protected]> AuthorDate: Wed Mar 4 17:22:46 2026 +0000 Use exarch to extract archives with custom validation --- atr/tasks/quarantine.py | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/atr/tasks/quarantine.py b/atr/tasks/quarantine.py index 083780b5..37905842 100644 --- a/atr/tasks/quarantine.py +++ b/atr/tasks/quarantine.py @@ -23,6 +23,7 @@ import pathlib import aiofiles.os import aioshutil +import exarch import atr.attestable as attestable import atr.config as config @@ -35,6 +36,7 @@ import atr.models.schema as schema import atr.models.sql as sql import atr.paths as paths import atr.storage.writers.revision as revision +import atr.tarzip as tarzip import atr.tasks.checks as checks import atr.util as util @@ -95,13 +97,26 @@ async def _extract_archives_to_cache( project_name: str, version_name: str, ) -> None: - # Cannot import as archives because that shadows the parameter name - import atr.archives - conf = config.get() cache_base = paths.get_cache_archives_dir() / project_name / version_name await aiofiles.os.makedirs(cache_base, exist_ok=True) + extraction_config = ( + exarch.SecurityConfig() + .max_file_size(conf.MAX_EXTRACT_SIZE) + .max_total_size(conf.MAX_EXTRACT_SIZE) + .max_file_count(tarzip.MAX_ARCHIVE_MEMBERS) + .max_compression_ratio(100.0) + .max_path_depth(32) + # Escaping the root is still disallowed by exarch even when symlinks are allowed + .allow_symlinks(True) + .allow_hardlinks(False) + .allow_absolute_paths(False) + # Too many archives use this for us to disallow it + # We could set to 0o444 after extraction anyway + .allow_world_writable(True) + ) + for archive in archives: cache_dir = cache_base / hashes.filesystem_cache_archives_key(archive.content_hash) if await aiofiles.os.path.isdir(cache_dir): @@ -111,11 +126,10 @@ async def _extract_archives_to_cache( await aiofiles.os.makedirs(extract_dir, exist_ok=True) try: await asyncio.to_thread( - atr.archives.extract, + exarch.extract_archive, archive_path, extract_dir, - max_size=conf.MAX_EXTRACT_SIZE, - chunk_size=conf.EXTRACT_CHUNK_SIZE, + extraction_config, ) except Exception: log.exception(f"Failed to extract archive {archive.rel_path} to cache") --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
