Skip to main content
Glama
test_path_traversal_security.py6.23 kB
""" Test path traversal security fix. Fixes vulnerability reported in: - https://github.com/BeehiveInnovations/zen-mcp-server/issues/293 - https://github.com/BeehiveInnovations/zen-mcp-server/issues/312 The vulnerability: is_dangerous_path() only did exact string matching, so /etc was blocked but /etc/passwd was allowed. Additionally, this fix properly handles home directory containers: - /home and C:\\Users are blocked (exact match only) - /home/user/project paths are allowed through is_dangerous_path() and handled by is_home_directory_root() in resolve_and_validate_path() """ from pathlib import Path from utils.security_config import is_dangerous_path class TestPathTraversalFix: """Test that subdirectories of dangerous system paths are blocked.""" def test_exact_match_still_works(self): """Test that exact dangerous paths are still blocked.""" assert is_dangerous_path(Path("/etc")) is True assert is_dangerous_path(Path("/usr")) is True assert is_dangerous_path(Path("/var")) is True def test_subdirectory_now_blocked(self): """Test that subdirectories of system paths are blocked (the fix).""" # These were allowed before the fix assert is_dangerous_path(Path("/etc/passwd")) is True assert is_dangerous_path(Path("/etc/shadow")) is True assert is_dangerous_path(Path("/etc/hosts")) is True assert is_dangerous_path(Path("/var/log/auth.log")) is True def test_deeply_nested_blocked(self): """Test that deeply nested system paths are blocked.""" assert is_dangerous_path(Path("/etc/ssh/sshd_config")) is True assert is_dangerous_path(Path("/usr/local/bin/python")) is True def test_root_blocked(self): """Test that root directory is blocked.""" assert is_dangerous_path(Path("/")) is True def test_safe_paths_allowed(self): """Test that safe paths are still allowed.""" # User project directories should be allowed assert is_dangerous_path(Path("/tmp/test")) is False assert is_dangerous_path(Path("/tmp/myproject/src")) is False def test_similar_names_not_blocked(self): """Test that paths with similar names are not blocked.""" # /etcbackup should NOT be blocked (it's not under /etc) assert is_dangerous_path(Path("/tmp/etcbackup")) is False assert is_dangerous_path(Path("/tmp/my_etc_files")) is False class TestHomeDirectoryHandling: """Test that home directory containers are handled correctly. Home containers (/home, C:\\Users) should only block the exact path, not subdirectories. Subdirectory access control is delegated to is_home_directory_root() in resolve_and_validate_path(). """ def test_home_container_blocked(self): """Test that /home itself is blocked.""" assert is_dangerous_path(Path("/home")) is True def test_home_subdirectories_allowed(self): """Test that /home subdirectories pass through is_dangerous_path(). These paths should NOT be blocked by is_dangerous_path() because: 1. /home/user/project is a valid user workspace 2. Access control for /home/username is handled by is_home_directory_root() """ # User home directories should pass is_dangerous_path() # (they are handled by is_home_directory_root() separately) assert is_dangerous_path(Path("/home/user")) is False assert is_dangerous_path(Path("/home/user/project")) is False assert is_dangerous_path(Path("/home/user/project/src/main.py")) is False def test_home_deeply_nested_allowed(self): """Test that deeply nested home paths are allowed.""" assert is_dangerous_path(Path("/home/user/documents/work/project/src")) is False class TestRegressionPrevention: """Regression tests for the specific vulnerability.""" def test_etc_passwd_blocked(self): """Test /etc/passwd is blocked (common attack target).""" assert is_dangerous_path(Path("/etc/passwd")) is True def test_etc_shadow_blocked(self): """Test /etc/shadow is blocked (password hashes).""" assert is_dangerous_path(Path("/etc/shadow")) is True class TestWindowsPathHandling: """Test Windows path handling with trailing backslash. Fixes issue reported in PR #353: Windows paths like C:\\ have trailing backslash which caused double separator issues with string prefix matching. Using Path.is_relative_to() resolves this correctly. """ def test_windows_root_drive_blocked(self): """Test that Windows root drive C:\\ is blocked.""" from pathlib import PureWindowsPath # Simulate Windows path behavior using PureWindowsPath # On Linux, we test the logic with PureWindowsPath to verify cross-platform correctness c_root = PureWindowsPath("C:\\") assert c_root.parent == c_root # Root check works def test_windows_dangerous_subdirectory_detection(self): """Test that Windows subdirectories are correctly detected as dangerous. This verifies the fix for the double backslash issue: - Before fix: "C:\\" + "\\" = "C:\\\\" which doesn't match "C:\\Users" - After fix: Path.is_relative_to() handles this correctly """ from pathlib import PureWindowsPath # Verify is_relative_to works correctly for Windows paths c_users = PureWindowsPath("C:\\Users") c_root = PureWindowsPath("C:\\") # This is the key test - subdirectory detection must work assert c_users.is_relative_to(c_root) is True # Deeper paths should also work c_users_admin = PureWindowsPath("C:\\Users\\Admin") assert c_users_admin.is_relative_to(c_root) is True assert c_users_admin.is_relative_to(c_users) is True def test_windows_path_not_relative_to_different_drive(self): """Test that paths on different drives are not related.""" from pathlib import PureWindowsPath d_path = PureWindowsPath("D:\\Data") c_root = PureWindowsPath("C:\\") # D: drive paths should not be relative to C: assert d_path.is_relative_to(c_root) is False

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/BeehiveInnovations/zen-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server