fix: path traversal false positive on filenames containing ..#35644
Conversation
…detection The path traversal check in _validate_and_resolve_path() used '".." in path' which is a substring match. This incorrectly rejected filenames containing ".." such as Next.js catch-all routes like ["...nextauth].ts". Replace with Path(path).parts membership check so that ".." is only rejected when it appears as a discrete path segment (actual traversal) rather than as part of a filename. The resolve() + relative_to() check below already provides the primary security boundary; this is defense-in-depth. Fixes langchain-ai#34961
|
Orb Code Review (powered by GLM 5.1 on Orb Cloud) PR #35644: fix: path traversal false positive on filenames containing ..FindingsCore fix: segment-based path traversal check ✅ Correct and well-targeted The old code used a simple substring check: if ".." in path or "~" in path:This incorrectly rejected any path containing The fix correctly uses path segments: segments = Path(path).parts
if ".." in segments or "~" in segments:This only rejects paths where
Security: The defense-in-depth Tests: Good test coverage with three new test cases covering filenames and directory names containing Summary: A clean, well-targeted fix for a false positive in the path traversal protection. The segment-based approach correctly distinguishes between actual traversal attempts ( Assessment: approve |
Description
Fixes #34961
FilesystemFileSearchMiddleware._validate_and_resolve_path()checks for path traversal using".." in path, which is a substring match. This incorrectly rejects any path where..appears anywhere in the string — including legitimate filenames like Next.js catch-all routes ([...nextauth].ts).Fix
Replace the substring check with a
Path(path).partsmembership check so that..is only rejected when it appears as a discrete path segment (i.e., actual directory traversal like/../or/foo/../bar), not when it appears inside a filename.Before:
After:
The same fix is applied to the
~check for consistency.Security is maintained by three layers of defense:
..and~as path segmentsPath.resolve()— canonicalizes the path, collapsing any..segmentsrelative_to()containment check — ensures the resolved path is within the root directoryTests
Added 3 tests to
TestPathTraversalSecurity:test_path_with_dots_in_filename_not_blocked—[...nextauth].tsglob workstest_path_with_dots_in_directory_name_not_blocked—my..folderdirectory workstest_grep_path_with_dots_in_filename— grep on[...nextauth].tsworksAll existing path traversal security tests continue to pass since
/../,~/, etc. contain../~as discrete path segments.