Skip to content

Commit 9c9f20f

Browse files
committed
fix: normalize include_paths -- strip backslashes, reject traversal, defense in depth
Sanitizer now matches the validation in IndexConfig.sanitize_paths: - Backslashes replaced with forward slashes - Leading/trailing whitespace and slashes stripped - Path traversal (..) entries rejected - Non-string and empty entries filtered 2 new tests: traversal rejection, backslash normalization. 35 total pass. Skipped findings: - Cache keyed by include_paths: not needed, cache cleared on re-index - repos.py truthy-only write: already fixed in previous commit - Test type hints: entire suite has zero, adding to 3 tests is inconsistent
1 parent 04ac019 commit 9c9f20f

2 files changed

Lines changed: 30 additions & 3 deletions

File tree

backend/services/dependency_analyzer.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -144,9 +144,15 @@ def build_dependency_graph(self, repo_path: str, include_paths: List[str] = None
144144

145145
# Sanitize include_paths from DB (could be corrupt jsonb)
146146
if include_paths:
147-
include_paths = [p for p in include_paths if isinstance(p, str) and p.strip()]
148-
if not include_paths:
149-
include_paths = None
147+
cleaned = []
148+
for p in include_paths:
149+
if not isinstance(p, str):
150+
continue
151+
p = p.replace('\\', '/').strip().strip('/')
152+
if not p or '..' in p.split('/'):
153+
continue
154+
cleaned.append(p)
155+
include_paths = cleaned or None
150156

151157
# Discover code files
152158
code_files = []

backend/tests/test_dependency_analyzer.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,27 @@ def test_include_paths_empty_list_scans_everything(self, analyzer, ts_repo):
308308
file_paths = set(graph['dependencies'].keys())
309309
assert any('backend' in f for f in file_paths)
310310

311+
def test_include_paths_traversal_rejected(self, analyzer, ts_repo):
312+
"""Path traversal attempts should be stripped, not crash"""
313+
graph = analyzer.build_dependency_graph(
314+
str(ts_repo),
315+
include_paths=['../etc/passwd', 'packages/effect', '../../secrets']
316+
)
317+
file_paths = set(graph['dependencies'].keys())
318+
# Traversal entries filtered, only packages/effect remains
319+
assert all('packages/effect' in f for f in file_paths)
320+
assert len(file_paths) > 0
321+
322+
def test_include_paths_backslash_normalized(self, analyzer, ts_repo):
323+
"""Windows-style backslashes should be normalized"""
324+
graph = analyzer.build_dependency_graph(
325+
str(ts_repo),
326+
include_paths=['packages\\effect']
327+
)
328+
file_paths = set(graph['dependencies'].keys())
329+
assert all('packages/effect' in f for f in file_paths)
330+
assert len(file_paths) > 0
331+
311332

312333
class TestGraphMetrics:
313334
"""Verify graph statistics are correct"""

0 commit comments

Comments
 (0)