Skip to content

Performance: Add rate limiting for PDF preview endpoint #504

@cbcoutinho

Description

@cbcoutinho

Problem

No rate limiting on the PDF preview endpoint. Rendering PDFs is CPU-intensive (PyMuPDF operations), and an attacker could exhaust server resources.

Impact:

  • Each request downloads entire PDF via WebDAV
  • PyMuPDF rendering is CPU-bound
  • High-scale factor (up to 5.0) increases rendering time
  • No concurrent request limits

Recommendation

Add rate limiting using a simple token bucket pattern (similar to passwords.py):

from functools import wraps
from collections import defaultdict
import time

_rate_limits = defaultdict(list)  # user_id -> [timestamp, ...]

def rate_limit(max_requests: int, window_seconds: int):
    """Rate limit decorator: max_requests per window_seconds per user."""
    def decorator(func):
        @wraps(func)
        async def wrapper(request: Request, *args, **kwargs):
            user_id = "unknown"
            try:
                user_id, _ = await validate_token_and_get_user(request)
            except Exception:
                pass
            
            now = time.time()
            user_requests = _rate_limits[user_id]
            user_requests[:] = [t for t in user_requests if now - t < window_seconds]
            
            if len(user_requests) >= max_requests:
                return JSONResponse(
                    {"success": False, "error": "Rate limit exceeded"},
                    status_code=429
                )
            
            user_requests.append(now)
            return await func(request, *args, **kwargs)
        return wrapper
    return decorator

# Apply: @rate_limit(max_requests=30, window_seconds=60)

Location

  • nextcloud_mcp_server/api/visualization.py

Priority

Critical - Must fix before merge to prevent DoS

Parent Issue

Part of #502

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions