fix: path traversal vulnerability - use prefix matching in is_dangerous_path()
The is_dangerous_path() function only did exact string matching, allowing attackers to bypass protection by accessing subdirectories: - /etc was blocked but /etc/passwd was allowed - C:\Windows was blocked but C:\Windows\System32\... was allowed This minimal fix changes is_dangerous_path() to use PREFIX MATCHING: - Now blocks dangerous directories AND all their subdirectories - Paths like /etcbackup are still allowed (not under /etc) - No changes to DANGEROUS_PATHS list Security: - Fixes CWE-22: Path Traversal vulnerability - Reported by: Team off-course (K-Shield.Jr 15th) Fixes #312 Fixes #293
This commit is contained in:
@@ -89,16 +89,47 @@ EXCLUDED_DIRS = {
|
||||
|
||||
def is_dangerous_path(path: Path) -> bool:
|
||||
"""
|
||||
Check if a path is in the dangerous paths list.
|
||||
Check if a path is in or under a dangerous directory.
|
||||
|
||||
Uses PREFIX MATCHING to block dangerous directories AND their subdirectories.
|
||||
For example, if "/etc" is in DANGEROUS_PATHS, both "/etc" and "/etc/passwd"
|
||||
will be blocked.
|
||||
|
||||
Args:
|
||||
path: Path to check
|
||||
|
||||
Returns:
|
||||
True if the path is dangerous and should not be accessed
|
||||
|
||||
Security:
|
||||
Fixes path traversal vulnerability (CWE-22) reported in:
|
||||
- https://github.com/BeehiveInnovations/zen-mcp-server/issues/293
|
||||
- https://github.com/BeehiveInnovations/zen-mcp-server/issues/312
|
||||
"""
|
||||
try:
|
||||
resolved = path.resolve()
|
||||
return str(resolved) in DANGEROUS_PATHS or resolved.parent == resolved
|
||||
resolved_str = str(resolved)
|
||||
|
||||
# Check 1: Root directory (filesystem root)
|
||||
if resolved.parent == resolved:
|
||||
return True
|
||||
|
||||
# Check 2: Exact match or subdirectory of dangerous paths
|
||||
for dangerous in DANGEROUS_PATHS:
|
||||
# Skip root "/" - already handled above
|
||||
if dangerous == "/":
|
||||
continue
|
||||
|
||||
# Exact match
|
||||
if resolved_str == dangerous:
|
||||
return True
|
||||
|
||||
# Subdirectory check: path starts with dangerous + separator
|
||||
# Use os.sep for platform-appropriate separator
|
||||
if resolved_str.startswith(dangerous + "/") or resolved_str.startswith(dangerous + "\\"):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
except Exception:
|
||||
return True # If we can't resolve, consider it dangerous
|
||||
|
||||
Reference in New Issue
Block a user