Skip to content

Commit a81bd91

Browse files
committed
security patch
1 parent 47e7350 commit a81bd91

2 files changed

Lines changed: 18 additions & 3 deletions

File tree

py-src/data_formulator/datalake/azure_blob_workspace.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -720,7 +720,12 @@ def import_session_zip(self, zip_data: io.BytesIO) -> dict:
720720
self.cleanup()
721721
for entry in workspace_entries:
722722
rel = entry[len("workspace/"):]
723-
self._upload_bytes(rel, zf.read(entry))
723+
# Guard against zip-slip: secure_filename strips
724+
# path separators and ".." components.
725+
safe_rel = secure_filename(rel)
726+
if not safe_rel:
727+
continue # skip entries that sanitise to empty
728+
self._upload_bytes(safe_rel, zf.read(entry))
724729
if not self._blob_exists(METADATA_FILENAME):
725730
self._init_metadata()
726731
# Invalidate caches since workspace blobs were replaced

py-src/data_formulator/datalake/cached_azure_blob_workspace.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,8 +221,18 @@ def __init__(
221221
# ------------------------------------------------------------------
222222

223223
def _cache_path(self, filename: str) -> Path:
224-
"""Return the local cache path for *filename*."""
225-
return self._cache_dir / filename
224+
"""Return the local cache path for *filename*.
225+
226+
Raises ``ValueError`` if the resolved path escapes the cache
227+
directory (defence-in-depth against path-traversal attacks).
228+
"""
229+
resolved = (self._cache_dir / filename).resolve()
230+
if not resolved.is_relative_to(self._cache_dir.resolve()):
231+
raise ValueError(
232+
f"Path traversal detected: {filename!r} resolves outside "
233+
f"the cache directory"
234+
)
235+
return resolved
226236

227237
# ------------------------------------------------------------------
228238
# Low-level blob overrides (write-through cache)

0 commit comments

Comments
 (0)