mirror of
https://github.com/NicolasBohn/NexQuant.git
synced 2026-07-27 23:47:46 +00:00
fix: Add Bandit security scanning and fix critical vulnerabilities
- Add Bandit security scanner to requirements and pre-commit hooks - Fix CWE-22 path traversal in tarfile/zipfile extraction (3 files) * Add _safe_extract() validation in submit.py, env.py, kaggle_crawler.py * Prevents malicious archives from writing outside target directory - Fix MD5 hashlib calls with usedforsecurity=False flag (2 files) * submission_format_test.txt files for checksum validation - Configure .bandit.yml for automated security scanning * Skip known false positives: B602 (subprocess), B701 (Jinja2) - Add security runbook documentation in docs/security/ - Add pre-commit hook scripts for automated Bandit scanning All 106 backtesting and security tests pass. Security issues resolved: B201, B202, B324 (9 total fixes)
This commit is contained in:
+18
-8
@@ -272,6 +272,23 @@ class Env(Generic[ASpecificEnvConf]):
|
||||
os.path.relpath(os.path.join(root, file), folder_path),
|
||||
)
|
||||
|
||||
def _safe_extract_zip(self, z: zipfile.ZipFile, path: str, files_to_extract: list[str] | None = None) -> None:
|
||||
"""Extract zipfile safely, preventing path traversal attacks (CWE-22)."""
|
||||
abs_path = os.path.realpath(path)
|
||||
members = [z.getinfo(f) for f in files_to_extract] if files_to_extract else z.infolist()
|
||||
for member in members:
|
||||
member_path = os.path.realpath(os.path.join(abs_path, member.filename))
|
||||
if not member_path.startswith(abs_path):
|
||||
raise ValueError(f"Attempted path traversal in zip file: {member.filename}")
|
||||
if files_to_extract is not None:
|
||||
for file_name in files_to_extract:
|
||||
try:
|
||||
z.extract(file_name, path)
|
||||
except KeyError:
|
||||
logger.warning(f"File {file_name} not found in cache zip.")
|
||||
else:
|
||||
z.extractall(path=path) # nosec B202:tarfile_unsafe_members - validated above
|
||||
|
||||
def unzip_a_file_into_a_folder(
|
||||
self, zip_file_path: str, folder_path: str, files_to_extract: list[str] | None = None
|
||||
) -> None:
|
||||
@@ -285,14 +302,7 @@ class Env(Generic[ASpecificEnvConf]):
|
||||
os.makedirs(folder_path)
|
||||
|
||||
with zipfile.ZipFile(zip_file_path, "r") as z:
|
||||
if files_to_extract is not None:
|
||||
for file_name in files_to_extract:
|
||||
try:
|
||||
z.extract(file_name, folder_path)
|
||||
except KeyError:
|
||||
logger.warning(f"File {file_name} not found in cache zip.")
|
||||
else:
|
||||
z.extractall(folder_path)
|
||||
self._safe_extract_zip(z, folder_path, files_to_extract)
|
||||
|
||||
@abstractmethod
|
||||
def prepare(self, *args, **kwargs) -> None: # type: ignore[no-untyped-def]
|
||||
|
||||
Reference in New Issue
Block a user