@@ -119,16 +119,67 @@ def get_project_dir(project_name: str) -> Path:
119119 # Try to get from registry
120120 project_path = get_project_path (project_name )
121121 if project_path :
122- return Path (project_path )
122+ # Resolve and validate the registered path
123+ resolved_path = project_path .resolve ()
124+ _validate_project_dir (resolved_path )
125+ return resolved_path
123126
124127 # Check if it's a direct path
125128 path = Path (project_name )
126129 if path .exists () and path .is_dir ():
127- return path
130+ # Resolve and validate the provided path
131+ resolved_path = path .resolve ()
132+ _validate_project_dir (resolved_path )
133+ return resolved_path
128134
129135 raise HTTPException (status_code = 404 , detail = f"Project not found: { project_name } " )
130136
131137
138+ def _validate_project_dir (resolved_path : Path ) -> None :
139+ """
140+ Validate that a project directory is within allowed boundaries.
141+
142+ Args:
143+ resolved_path: The resolved project path to validate
144+
145+ Raises:
146+ HTTPException: If the path is outside allowed boundaries or is dangerous
147+ """
148+ # Blocklist for dangerous locations
149+ dangerous_roots = [
150+ Path ("/" ).resolve (), # Root
151+ Path ("/etc" ).resolve (), # System config
152+ Path ("/var" ).resolve (), # System variables
153+ Path .home ().resolve (), # User home (allow subpaths, block direct home)
154+ ]
155+
156+ # Check if path is in dangerous locations
157+ for dangerous in dangerous_roots :
158+ try :
159+ if dangerous in resolved_path .parents or dangerous == resolved_path :
160+ raise HTTPException (
161+ status_code = 404 ,
162+ detail = f"Project not found: { resolved_path } "
163+ )
164+ except (ValueError , OSError ):
165+ pass
166+
167+ # Ensure path is contained within an allowed root
168+ allowed_root = Path .cwd ().resolve ()
169+
170+ try :
171+ if resolved_path .is_relative_to (allowed_root ):
172+ return
173+ except ValueError :
174+ pass
175+
176+ # Path is not within allowed boundaries
177+ raise HTTPException (
178+ status_code = 404 ,
179+ detail = f"Project not found: { resolved_path } "
180+ )
181+
182+
132183# ============================================================================
133184# Endpoints
134185# ============================================================================
0 commit comments