Skip to content

Fix TOCTOU race condition in document upload endpoint #448

@kovtcharov

Description

@kovtcharov

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

  1. Open file with `O_NOFOLLOW` and hold file descriptor throughout processing
  2. Use `fstat()` on open fd instead of `stat()` on path
  3. Compute hash, extract text, and index all from the same open fd
  4. Add file-level locking (`fcntl.flock`) for concurrent upload protection
  5. Validate inode hasn't changed between steps

Files

  • src/gaia/chat/ui/server.py (lines 313-341, upload_by_path endpoint)

Acceptance Criteria

  • File operations use consistent fd, not repeated path lookups
  • Concurrent uploads of same file are serialized
  • Test: file deleted during upload returns clean error
  • Test: concurrent upload of same file doesn't corrupt state

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingchatChat SDK changesp0high priorityragRAG system changesrobustnessReliability, error handling, and hardeningsecuritySecurity-sensitive changes

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions