Files
my-pal-mcp-server/utils/security_config.py
谢栋梁 9ed15f405a 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
2025-12-03 15:29:57 +08:00

136 lines
3.0 KiB
Python

"""
Security configuration and path validation constants
This module contains security-related constants and configurations
for file access control.
"""
from pathlib import Path
# Dangerous paths that should never be scanned
# These would give overly broad access and pose security risks
DANGEROUS_PATHS = {
"/",
"/etc",
"/usr",
"/bin",
"/var",
"/root",
"/home",
"C:\\",
"C:\\Windows",
"C:\\Program Files",
"C:\\Users",
}
# Directories to exclude from recursive file search
# These typically contain generated code, dependencies, or build artifacts
EXCLUDED_DIRS = {
# Python
"__pycache__",
".venv",
"venv",
"env",
".env",
"*.egg-info",
".eggs",
"wheels",
".Python",
".mypy_cache",
".pytest_cache",
".tox",
"htmlcov",
".coverage",
"coverage",
# Node.js / JavaScript
"node_modules",
".next",
".nuxt",
"bower_components",
".sass-cache",
# Version Control
".git",
".svn",
".hg",
# Build Output
"build",
"dist",
"target",
"out",
# IDEs
".idea",
".vscode",
".sublime",
".atom",
".brackets",
# Temporary / Cache
".cache",
".temp",
".tmp",
"*.swp",
"*.swo",
"*~",
# OS-specific
".DS_Store",
"Thumbs.db",
# Java / JVM
".gradle",
".m2",
# Documentation build
"_build",
"site",
# Mobile development
".expo",
".flutter",
# Package managers
"vendor",
}
def is_dangerous_path(path: Path) -> bool:
"""
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()
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