You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
SQL injection anti-pattern in index creation (database.py:278-281): Changed f-string interpolation in DDL helper to parameterized query using text(...).bindparams(...). The index name was hardcoded so not directly exploitable, but the pattern could be copied to user-facing code.
Timing attack on admin API key comparison (state.py:467): Changed string != comparison to hmac.compare_digest() to prevent timing side-channel attacks on the admin API key.
Bug Fixes
VRAM state inconsistency on model load failure (vram_manager.py:120-148): Added snapshot of loaded_models before VRAM freeing; restores snapshot if load_model() raises or VRAMExceededError occurs. Previously, a failed load could free VRAM without adding the model.
load_model always returns True in Ollama backend (ollama.py:330-388): Returns False when the model doesn't exist, when both load attempts fail, or on generic exceptions. Previously all code paths returned True even on genuine failures.
Duplicate background task registration (lifecycle.py:197-218): Removed duplicate registration of background_cache_cleanup_task and background_dlq_retry_task that were creating redundant coroutines.
Performance Improvements
Bulk delete for expired cache entries (persistent_cache.py): Replaced O(N) row-by-row session.delete() loop with single session.execute(delete(Model).where(...)) bulk SQL delete.
Efficient cache count queries (persistent_cache.py): Replaced len(session.execute(...).scalars().all()) with session.scalar(select(func.count()).where(...)) to avoid loading all rows into memory.
Bounded prompt analysis cache (router.py): Changed _PROMPT_ANALYSIS_CACHE from unbounded dict to OrderedDict with max 4096 entries and LRU eviction on write. Added move_to_end on read access.
Bounded benchmark cache (benchmark_db.py): Changed _benchmarks_for_models_cache from unbounded frozenset-keyed dict to OrderedDict with max 512 entries and LRU eviction.
Async DB call for feedback scores (router.py:1291): Changed synchronous self._get_model_feedback_scores() call in async _keyword_dispatch to await asyncio.to_thread(...) to avoid blocking the event loop.
Async file I/O for provider.db download (lifecycle.py:441): Wrapped blocking open(...).write(...) in await asyncio.to_thread(_write_temp) to prevent event loop stalls during download.
Single-transaction bulk upsert (benchmark_db.py:166-186): Moved session and commit outside the per-item loop so all benchmark rows are written in a single transaction.