Unbounded userdata traversal blocks the aiohttp event loop
- Dominant language
- Python
- Stars
- 133k
- Forks
- 15.7k
- Avg merge
- 1d 7h
- Merged PRs (30d)
- 158
Description
Unbounded userdata traversal blocks the aiohttp event loop and WebSocket delivery
- Both userdata listing endpoints traverse user-controlled directory trees synchronously.
- The v2 endpoint always recurses, stats every file, accumulates all entries, and sorts the full result.
- Because this runs on aiohttp's event loop, a large or slow tree delays HTTP and WebSocket traffic for every client.
Evidence and suggested direction
`app/user_manager.py:206-210` executes `glob.glob(..., recursive=True)`, `os.path.isfile`, and optionally the per-file metadata calls at `app/user_manager.py:27-32` directly inside the async `/userdata` handler. The v2 route is unconditionally recursive: `app/user_manager.py:281-316` runs `os.walk`, calls `os.stat` for each file, accumulates the complete tree in memory, and sorts it before returning. Neither route has an executor boundary, pagination, or a traversal/result cap.
These handlers run on the same aiohttp event loop as `/ws` in `server.py`. A user-controlled large directory tree, or a user directory on slow/network-backed storage, can monopolize that loop and delay WebSocket events, heartbeats, and unrelated requests. Existing userdata tests verify returned data and error cases but do not verify event-loop responsiveness or bound the amount of work.
Please move traversal/stat work off the event loop and add a bounded API contract (pagination and/or an explicit maximum result/work budget). A regression test can inject a deliberately blocked filesystem traversal while proving an unrelated coroutine or WebSocket event continues to make progress.
Single-file upload/move/delete calls also use synchronous filesystem operations in async handlers, but they are bounded and are noted only as related hardening, not part of this unbounded-traversal finding.
Reviewed at `12d5279438bfefc058a269eae805ceab6047777f`.
Contributor guide
Research direction
Read app/user_manager.py:206-210 and 281-316, then inspect the /ws event-loop setup in server.py and run the existing userdata tests. Done means traversal and stat work no longer blocks the loop, the API has an explicit bounded contract, and a regression test shows unrelated coroutine or WebSocket progress during blocked traversal.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- api, backend, performance, testing
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100