Skip to content

fix: race conditions in file watcher, parser cache, and server state #42

@rosschurchill

Description

@rosschurchill

Problem

  1. TOCTOU in file watcherwatcher.py checks file existence then reads it; file can be deleted between check and read
  2. Unsynchronized parser cacheget_parser() in parser_phase.py has no locking; concurrent indexing threads can corrupt the cache or double-initialize parsers
  3. Scattered global stateserver.py uses separate _storage and _lock module-level globals with global statements, making mutation surface hard to reason about
  4. No rate limiting — MCP server accepts unlimited requests with no throttling

Proposed fix

  • RACE-1: Wrap read_file() call in try/except (FileNotFoundError, PermissionError, OSError)
  • RACE-2: Add threading.Lock() with double-checked locking pattern in get_parser()
  • RACE-3: Replace scattered globals with _ServerState dataclass
  • AUTH-1: Add sliding-window rate limiter (200 requests / 60 seconds)

Files to change

  • src/axon/core/ingestion/watcher.py
  • src/axon/core/ingestion/parser_phase.py
  • src/axon/mcp/server.py

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