Skip to content

Commit dc7d6b7

Browse files
Merge pull request CodeGraphContext#741 from jannahopp/fix/security-quick-wins
fix: address security findings (Zip Slip, importlib, pytest dep)
2 parents 7269a1e + 745978a commit dc7d6b7

File tree

3 files changed

+17
-12
lines changed

3 files changed

+17
-12
lines changed

pyproject.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ dependencies = [
2525
"tree-sitter>=0.21.0",
2626
"tree-sitter-language-pack>=0.6.0",
2727
"pyyaml",
28-
"pytest",
2928
"nbformat",
3029
"nbconvert>=7.16.6",
3130
"pathspec>=0.12.1",

src/codegraphcontext/core/cgc_bundle.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,9 +161,13 @@ def import_from_bundle(
161161
with tempfile.TemporaryDirectory() as temp_dir:
162162
temp_path = Path(temp_dir)
163163

164-
# Step 1: Extract ZIP
164+
# Step 1: Extract ZIP (with Zip Slip protection)
165165
info_logger("Extracting bundle...")
166166
with zipfile.ZipFile(bundle_path, 'r') as zip_ref:
167+
for entry in zip_ref.namelist():
168+
resolved = (temp_path / entry).resolve()
169+
if not str(resolved).startswith(str(temp_path.resolve())):
170+
return False, f"Zip Slip detected: entry '{entry}' escapes target directory"
167171
zip_ref.extractall(temp_path)
168172

169173
# Step 2: Validate bundle

src/codegraphcontext/tools/package_resolver.py

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# src/codegraphcontext/tools/package_resolver.py
2-
import importlib
2+
import importlib.util
33
import stdlibs
44
from pathlib import Path
55
import subprocess
@@ -10,25 +10,27 @@
1010
def _get_python_package_path(package_name: str) -> Optional[str]:
1111
"""
1212
Finds the local installation path of a Python package.
13+
Uses importlib.util.find_spec() to locate the module without executing its code.
1314
"""
1415
try:
1516
debug_log(f"Getting local path for Python package: {package_name}")
16-
module = importlib.import_module(package_name)
17-
if hasattr(module, '__file__') and module.__file__:
18-
module_file = Path(module.__file__)
17+
spec = importlib.util.find_spec(package_name)
18+
if spec is None:
19+
return None
20+
if spec.origin and spec.origin != "frozen":
21+
module_file = Path(spec.origin)
1922
if module_file.name == '__init__.py':
2023
return str(module_file.parent)
2124
elif package_name in stdlibs.module_names:
2225
return str(module_file)
2326
else:
2427
return str(module_file.parent)
25-
elif hasattr(module, '__path__'):
26-
if isinstance(module.__path__, list) and module.__path__:
27-
return str(Path(module.__path__[0]))
28-
else:
29-
return str(Path(str(module.__path__)))
28+
elif spec.submodule_search_locations:
29+
locations = list(spec.submodule_search_locations)
30+
if locations:
31+
return str(Path(locations[0]))
3032
return None
31-
except ImportError:
33+
except (ModuleNotFoundError, ValueError):
3234
return None
3335
except Exception as e:
3436
debug_log(f"Error getting local path for {package_name}: {e}")

0 commit comments

Comments
 (0)