Problem
src/gaia/chat/ui/server.py:313-341 has a time-of-check-time-of-use (TOCTOU) vulnerability:
safe_filepath = _sanitize_document_path(request.filepath)
if not safe_filepath.exists(): # CHECK
raise HTTPException(status_code=404)
# ... time passes ...
file_hash = _compute_file_hash(safe_filepath) # USE — file could have changed
Between validation and hashing, the file could be modified, deleted, or replaced with a symlink.
Impact
- File deleted between check and hash → unhandled exception
- File replaced with symlink → potential path traversal
- Concurrent uploads of same file → inconsistent database state
- Hash computed on modified content but metadata saved from original
Proposed Fix
- Open file with `O_NOFOLLOW` and hold file descriptor throughout processing
- Use `fstat()` on open fd instead of `stat()` on path
- Compute hash, extract text, and index all from the same open fd
- Add file-level locking (`fcntl.flock`) for concurrent upload protection
- Validate inode hasn't changed between steps
Files
src/gaia/chat/ui/server.py (lines 313-341, upload_by_path endpoint)
Acceptance Criteria
Problem
src/gaia/chat/ui/server.py:313-341has a time-of-check-time-of-use (TOCTOU) vulnerability:Between validation and hashing, the file could be modified, deleted, or replaced with a symlink.
Impact
Proposed Fix
Files
src/gaia/chat/ui/server.py(lines 313-341, upload_by_path endpoint)Acceptance Criteria