@@ -224,6 +224,10 @@ def _serve_static_file(self, path):
224224 try :
225225 # Remove /static/ prefix and ensure a relative path
226226 file_path = path [8 :].lstrip ('/\\ ' ) # Remove '/static/' and any leading separators
227+ if not file_path :
228+ self ._send_error_response (404 , 'Not Found' )
229+ return
230+
227231 filename = os .path .basename (file_path )
228232
229233 # Try to get cached static file from server instance
@@ -248,6 +252,17 @@ def _serve_static_file(self, path):
248252 static_dir = os .path .realpath (os .path .join (portal_dir , 'static' ))
249253 # Build and normalize full path to requested file
250254 full_path = os .path .realpath (os .path .join (static_dir , file_path ))
255+
256+ # Enforce that the requested file stays under static_dir
257+ if os .path .commonpath ([static_dir , full_path ]) != static_dir :
258+ log_warning ('Portal' , f'Blocked path traversal attempt: { path } ' )
259+ self ._send_error_response (403 , 'Forbidden' )
260+ return
261+
262+ if not os .path .isfile (full_path ):
263+ self ._send_error_response (404 , 'Not Found' )
264+ return
265+ full_path = os .path .realpath (os .path .join (static_dir , file_path ))
251266
252267 # Security check: ensure file is within static directory
253268 if os .path .commonpath ([static_dir , full_path ]) != static_dir :
0 commit comments