Files
gh-christianlouis-docuelevate/app/api/common.py
T
copilot-swe-agent[bot] 551b23a80c fix(security): reduce code duplication and fix security issues in OAuth and file handling
- Extract common OAuth token exchange logic to shared utility (oauth_helper.py)
- Remove sensitive data logging (client_secret, authorization codes)
- Add path traversal validation in resolve_file_path()
- Add input validation for rclone destination parameter
- Replace bare Exception catches with specific exception types
- Use RuntimeError instead of generic Exception for better error handling

Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-02-08 08:26:10 +00:00

67 lines
2.0 KiB
Python

"""
Common utilities for API routes
"""
import logging
import os
from pathlib import Path
from sqlalchemy.orm import Session
from fastapi import Depends, HTTPException, status
from app.database import SessionLocal
from app.config import settings
# Set up logging
logger = logging.getLogger(__name__)
def get_db():
"""Database dependency injection for routes"""
db = SessionLocal()
try:
yield db
finally:
db.close()
def resolve_file_path(file_path: str, subfolder: str = None) -> str:
"""
Resolves a file path to an absolute path with path traversal protection.
If the path is not absolute, it will be joined with the workdir path.
Optionally, can include a subfolder like 'processed'.
Security: Validates that the resolved path stays within the workdir
to prevent path traversal attacks (e.g., ../../etc/passwd).
Args:
file_path: The file path to resolve
subfolder: Optional subfolder within workdir
Returns:
The validated absolute file path
Raises:
HTTPException: If the path attempts to escape the workdir
"""
# Build the base directory
if subfolder:
base_dir = Path(settings.workdir) / subfolder
else:
base_dir = Path(settings.workdir)
# Resolve the file path
if not os.path.isabs(file_path):
resolved_path = (base_dir / file_path).resolve()
else:
resolved_path = Path(file_path).resolve()
# Ensure the resolved path is within the base directory (path traversal protection)
try:
resolved_path.relative_to(base_dir.resolve())
except ValueError:
# Path is outside the base directory - potential path traversal attack
logger.warning(f"Path traversal attempt detected: {file_path} -> {resolved_path}")
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Invalid file path: path traversal not allowed"
)
return str(resolved_path)