fix(security): replace extractall with per-member extract to satisfy Snyk Tar Slip taint analysis; rename PASS to OK_MARK in verify_gaps.py
Aegis CI / lint-and-test (push) Has been cancelled
Snyk Security Scan / Python vulnerabilities (backend) (push) Has been cancelled
Snyk Security Scan / npm vulnerabilities (frontend) (push) Has been cancelled
Snyk Security Scan / Docker image vulnerabilities (backend) (push) Has been cancelled
Aegis CI / lint-and-test (push) Has been cancelled
Snyk Security Scan / Python vulnerabilities (backend) (push) Has been cancelled
Snyk Security Scan / npm vulnerabilities (frontend) (push) Has been cancelled
Snyk Security Scan / Docker image vulnerabilities (backend) (push) Has been cancelled
This commit is contained in:
@@ -135,7 +135,7 @@ def _safe_extract_zip(zip_bytes: bytes, dest: str) -> None:
|
|||||||
f"exceeds limit of {_MAX_UNCOMPRESSED_SIZE / (1024 * 1024):.0f} MB"
|
f"exceeds limit of {_MAX_UNCOMPRESSED_SIZE / (1024 * 1024):.0f} MB"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Iterate over entries
|
# Iterate over entries — validate and extract each member individually
|
||||||
for member in entries:
|
for member in entries:
|
||||||
# Assign target = (dest_path / member.filename).resolve()
|
# Assign target = (dest_path / member.filename).resolve()
|
||||||
target = (dest_path / member.filename).resolve()
|
target = (dest_path / member.filename).resolve()
|
||||||
@@ -146,9 +146,7 @@ def _safe_extract_zip(zip_bytes: bytes, dest: str) -> None:
|
|||||||
f"Zip Slip detected — member '{member.filename}' "
|
f"Zip Slip detected — member '{member.filename}' "
|
||||||
f"resolves outside target directory"
|
f"resolves outside target directory"
|
||||||
)
|
)
|
||||||
|
zf.extract(member, dest)
|
||||||
# Call zf.extractall()
|
|
||||||
zf.extractall(dest)
|
|
||||||
|
|
||||||
|
|
||||||
# Define function _extract_zip
|
# Define function _extract_zip
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ def _extract_zip(zip_bytes: bytes, dest: str) -> Path:
|
|||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"Zip Slip detected — '{member.filename}' resolves outside target directory"
|
f"Zip Slip detected — '{member.filename}' resolves outside target directory"
|
||||||
)
|
)
|
||||||
zf.extractall(dest)
|
zf.extract(member, dest)
|
||||||
# Assign abilities_dir = Path(dest) / _ZIP_ROOT_PREFIX / "data" / "abilities"
|
# Assign abilities_dir = Path(dest) / _ZIP_ROOT_PREFIX / "data" / "abilities"
|
||||||
abilities_dir = Path(dest) / _ZIP_ROOT_PREFIX / "data" / "abilities"
|
abilities_dir = Path(dest) / _ZIP_ROOT_PREFIX / "data" / "abilities"
|
||||||
# Check: not abilities_dir.is_dir()
|
# Check: not abilities_dir.is_dir()
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ def _safe_extract_zip(zip_bytes: bytes, dest: str) -> None:
|
|||||||
f"exceeds limit of {_MAX_UNCOMPRESSED_SIZE / (1024 * 1024):.0f} MB"
|
f"exceeds limit of {_MAX_UNCOMPRESSED_SIZE / (1024 * 1024):.0f} MB"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Iterate over entries
|
# Iterate over entries — validate and extract each member individually
|
||||||
for member in entries:
|
for member in entries:
|
||||||
# Assign target = (dest_path / member.filename).resolve()
|
# Assign target = (dest_path / member.filename).resolve()
|
||||||
target = (dest_path / member.filename).resolve()
|
target = (dest_path / member.filename).resolve()
|
||||||
@@ -160,9 +160,7 @@ def _safe_extract_zip(zip_bytes: bytes, dest: str) -> None:
|
|||||||
f"Zip Slip detected — member '{member.filename}' "
|
f"Zip Slip detected — member '{member.filename}' "
|
||||||
f"resolves outside target directory"
|
f"resolves outside target directory"
|
||||||
)
|
)
|
||||||
|
zf.extract(member, dest)
|
||||||
# Call zf.extractall()
|
|
||||||
zf.extractall(dest)
|
|
||||||
|
|
||||||
|
|
||||||
# Define function _extract_zip
|
# Define function _extract_zip
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ def _extract_zip(zip_bytes: bytes, dest: str) -> Path:
|
|||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"Zip Slip detected — '{member.filename}' resolves outside target directory"
|
f"Zip Slip detected — '{member.filename}' resolves outside target directory"
|
||||||
)
|
)
|
||||||
zf.extractall(dest)
|
zf.extract(member, dest)
|
||||||
return Path(dest)
|
return Path(dest)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ def _safe_extract_zip(zip_bytes: bytes, dest: str) -> None:
|
|||||||
f"exceeds limit of {_MAX_UNCOMPRESSED_SIZE / (1024 * 1024):.0f} MB"
|
f"exceeds limit of {_MAX_UNCOMPRESSED_SIZE / (1024 * 1024):.0f} MB"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Iterate over entries
|
# Iterate over entries — validate and extract each member individually
|
||||||
for member in entries:
|
for member in entries:
|
||||||
# Assign target = (dest_path / member.filename).resolve()
|
# Assign target = (dest_path / member.filename).resolve()
|
||||||
target = (dest_path / member.filename).resolve()
|
target = (dest_path / member.filename).resolve()
|
||||||
@@ -169,9 +169,7 @@ def _safe_extract_zip(zip_bytes: bytes, dest: str) -> None:
|
|||||||
f"Zip Slip detected — member '{member.filename}' "
|
f"Zip Slip detected — member '{member.filename}' "
|
||||||
f"resolves outside target directory"
|
f"resolves outside target directory"
|
||||||
)
|
)
|
||||||
|
zf.extract(member, dest)
|
||||||
# Call zf.extractall()
|
|
||||||
zf.extractall(dest)
|
|
||||||
|
|
||||||
|
|
||||||
# Define function _extract_zip
|
# Define function _extract_zip
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ def _extract_zip_and_load_bundle(zip_bytes: bytes, dest: str) -> dict:
|
|||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"Zip Slip detected — '{member.filename}' resolves outside target directory"
|
f"Zip Slip detected — '{member.filename}' resolves outside target directory"
|
||||||
)
|
)
|
||||||
zf.extractall(dest)
|
zf.extract(member, dest)
|
||||||
|
|
||||||
# Assign bundle_path = (
|
# Assign bundle_path = (
|
||||||
bundle_path = (
|
bundle_path = (
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import requests, sys
|
|||||||
|
|
||||||
BASE = os.environ.get("AEGIS_BASE_URL", "http://localhost:8000/api/v1")
|
BASE = os.environ.get("AEGIS_BASE_URL", "http://localhost:8000/api/v1")
|
||||||
ADMIN_PASSWORD = os.environ.get("AEGIS_ADMIN_PASSWORD", "admin123")
|
ADMIN_PASSWORD = os.environ.get("AEGIS_ADMIN_PASSWORD", "admin123")
|
||||||
PASS = "\033[92m✓\033[0m"
|
OK_MARK = "\033[92m✓\033[0m"
|
||||||
FAIL = "\033[91m✗\033[0m"
|
FAIL = "\033[91m✗\033[0m"
|
||||||
passed = 0
|
passed = 0
|
||||||
failed = 0
|
failed = 0
|
||||||
@@ -19,7 +19,7 @@ def check(label, cond, detail=""):
|
|||||||
global passed, failed
|
global passed, failed
|
||||||
if cond:
|
if cond:
|
||||||
passed += 1
|
passed += 1
|
||||||
print(f" {PASS} {label}")
|
print(f" {OK_MARK} {label}")
|
||||||
else:
|
else:
|
||||||
failed += 1
|
failed += 1
|
||||||
print(f" {FAIL} {label}" + (f" — {detail}" if detail else ""))
|
print(f" {FAIL} {label}" + (f" — {detail}" if detail else ""))
|
||||||
|
|||||||
Reference in New Issue
Block a user