Files
my-pal-mcp-server/utils/security_config.py
Fahad b5004b91fc Major new addition: refactor tool
Supports decomposing large components and files, finding codesmells, finding modernizing opportunities as well as code organization opportunities. Fix this mega-classes today!
Line numbers added to embedded code for better references from model -> claude
2025-06-15 06:00:01 +04:00

175 lines
4.6 KiB
Python

"""
Security configuration and path validation constants
This module contains security-related constants and configurations
for file access control and workspace management.
"""
import os
from pathlib import Path
# Dangerous paths that should never be used as WORKSPACE_ROOT
# These would give overly broad access and pose security risks
DANGEROUS_WORKSPACE_PATHS = {
"/",
"/etc",
"/usr",
"/bin",
"/var",
"/root",
"/home",
"/workspace", # Container path - WORKSPACE_ROOT should be host path
"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",
}
# MCP signature files - presence of these indicates the MCP's own directory
# Used to prevent the MCP from scanning its own codebase
MCP_SIGNATURE_FILES = {
"zen_server.py",
"server.py",
"tools/precommit.py",
"utils/file_utils.py",
"prompts/tool_prompts.py",
}
# Workspace configuration
WORKSPACE_ROOT = os.environ.get("WORKSPACE_ROOT")
CONTAINER_WORKSPACE = Path("/workspace")
def validate_workspace_security(workspace_root: str) -> None:
"""
Validate that WORKSPACE_ROOT is set to a safe directory.
Args:
workspace_root: The workspace root path to validate
Raises:
RuntimeError: If the workspace root is unsafe
"""
if not workspace_root:
return
# Resolve to canonical path for comparison
resolved_workspace = Path(workspace_root).resolve()
# Special check for /workspace - common configuration mistake
if str(resolved_workspace) == "/workspace":
raise RuntimeError(
f"Configuration Error: WORKSPACE_ROOT should be set to the HOST path, not the container path. "
f"Found: WORKSPACE_ROOT={workspace_root} "
f"Expected: WORKSPACE_ROOT should be set to your host directory path (e.g., $HOME) "
f"that contains all files Claude might reference. "
f"This path gets mounted to /workspace inside the Docker container."
)
# Check against other dangerous paths
if str(resolved_workspace) in DANGEROUS_WORKSPACE_PATHS:
raise RuntimeError(
f"Security Error: WORKSPACE_ROOT '{workspace_root}' is set to a dangerous system directory. "
f"This would give access to critical system files. "
f"Please set WORKSPACE_ROOT to a specific project directory."
)
# Additional check: prevent filesystem root
if resolved_workspace.parent == resolved_workspace:
raise RuntimeError(
f"Security Error: WORKSPACE_ROOT '{workspace_root}' cannot be the filesystem root. "
f"This would give access to the entire filesystem. "
f"Please set WORKSPACE_ROOT to a specific project directory."
)
def get_security_root() -> Path:
"""
Determine the security boundary for file access.
Returns:
Path object representing the security root directory
"""
# In Docker: use /workspace (container directory)
# In tests/direct mode: use WORKSPACE_ROOT (host directory)
if CONTAINER_WORKSPACE.exists():
# Running in Docker container
return CONTAINER_WORKSPACE
elif WORKSPACE_ROOT:
# Running in tests or direct mode with WORKSPACE_ROOT set
return Path(WORKSPACE_ROOT).resolve()
else:
# Fallback for backward compatibility (should not happen in normal usage)
return Path.home()
# Validate security on import if WORKSPACE_ROOT is set
if WORKSPACE_ROOT:
validate_workspace_security(WORKSPACE_ROOT)
# Export the computed security root
SECURITY_ROOT = get_security_root()