fix: validate download path containment in runner
Resolve and contain the user-supplied filename before serving it from the runner's /files endpoint. Also raise a 404 (instead of returning None) when the downloads folder is unset, and use the resolved basename for Content-Disposition.
This commit is contained in:
@@ -209,6 +209,17 @@ def _configure_server_app(args: argparse.Namespace):
|
||||
logger.warning(f"Unknown transport type: {args.transport}")
|
||||
|
||||
|
||||
def _resolve_download_path(folder: str, filename: str) -> Path:
|
||||
"""Resolve a download path and ensure it stays within the downloads folder."""
|
||||
allowed_base = Path(folder).resolve()
|
||||
file_path = (allowed_base / filename).resolve()
|
||||
|
||||
if not file_path.is_relative_to(allowed_base):
|
||||
raise HTTPException(status_code=403, detail="Access denied")
|
||||
|
||||
return file_path
|
||||
|
||||
|
||||
def _setup_webrtc_routes(app: FastAPI, args: argparse.Namespace):
|
||||
"""Set up WebRTC-specific routes."""
|
||||
try:
|
||||
@@ -250,16 +261,16 @@ def _setup_webrtc_routes(app: FastAPI, args: argparse.Namespace):
|
||||
async def download_file(filename: str):
|
||||
"""Handle file downloads."""
|
||||
if not args.folder:
|
||||
logger.warning(f"Attempting to dowload {filename}, but downloads folder not setup.")
|
||||
return
|
||||
logger.warning(f"Attempting to download {filename}, but downloads folder not setup.")
|
||||
raise HTTPException(404)
|
||||
|
||||
file_path = Path(args.folder) / filename
|
||||
if not os.path.exists(file_path):
|
||||
file_path = _resolve_download_path(args.folder, filename)
|
||||
if not file_path.exists():
|
||||
raise HTTPException(404)
|
||||
|
||||
media_type, _ = mimetypes.guess_type(file_path)
|
||||
|
||||
return FileResponse(path=file_path, media_type=media_type, filename=filename)
|
||||
return FileResponse(path=file_path, media_type=media_type, filename=file_path.name)
|
||||
|
||||
# Initialize the SmallWebRTC request handler
|
||||
small_webrtc_handler: SmallWebRTCRequestHandler = SmallWebRTCRequestHandler(
|
||||
|
||||
Reference in New Issue
Block a user