46 lines
2.9 KiB
Markdown
46 lines
2.9 KiB
Markdown
# Аудит Sonnet — результаты
|
||
|
||
## Ключевые цифры
|
||
|
||
- **48 проблем** найдено
|
||
- **14 CRITICAL**, **15 HIGH**, **19 MEDIUM**
|
||
- 17 файлов проанализировано
|
||
|
||
## ТОП-5 срочных
|
||
|
||
1. **upload.py:28** — Path Traversal: `filename` без `os.path.basename()` → `../../etc/passwd`
|
||
2. **app.js:79,495-520,497,703,708** — XSS × 5 мест: `innerHTML` без `escHtml()` на данных от LLM
|
||
3. **grouping.py:76** — `supplements_list.remove(s)` в итерации → пропуск элементов
|
||
4. **spec_events.py:15** — `MAX(seq)+1` без блокировки → race condition на seq
|
||
5. **prompts.py:40,73,86** — 3 race conditions: seed/save/activate без транзакций
|
||
|
||
## Что я понял
|
||
|
||
### Мои косяки (надо чинить)
|
||
|
||
1. **XSS в 5 местах** — `escHtml` не везде. `counterparty`, `own_number`, `filename`, `contract_number` — всё от LLM, всё в innerHTML без экранирования. Тупо пропустил.
|
||
|
||
2. **`supplements_list.remove(s)` в цикле** — реальный баг в grouping.py:76. При удалении элемента из списка во время итерации for пропускаются элементы. Может ломать группировку.
|
||
|
||
3. **`syncDB()` без await** — fire-and-forget. Если сервер не ответил — не узнаем. БД рассинхронится с таблицей.
|
||
|
||
4. **`delete_by_document` удаляет spec_current для ВСЕГО контракта** — если у контракта 3 supplements, удаление одного затирает spec_current для двух других. Серьёзный баг в supplements.py.
|
||
|
||
5. **`verify=False` в httpx** — отключена проверка SSL. MITM-уязвимость в classify.py и llm_prompt.py.
|
||
|
||
### Что НЕ надо чинить (не критично)
|
||
|
||
- Dead code (дубликат `_handle_cleanup`) — не влияет на работу.
|
||
- `_serialize` мутирует словарь — косметика.
|
||
- `v1.0.175` хардкод — пока сойдёт.
|
||
- `.doc` без fallback — формат редкость.
|
||
- `errors="ignore"` в парсинге — мелочь.
|
||
|
||
### Что Sonnet нашёл сверх моего анализа
|
||
|
||
- `MAX(seq)+1` race condition — я не подумал про параллельные запросы к spec_events.
|
||
- `apply_groups()` без транзакций — я не проверил атомарность.
|
||
- `_safe_json_parse()` возвращает None для `"null"` — edge case который я упустил.
|
||
- DoS через `keep_ids` без лимита — не подумал про O(N²).
|
||
- `get()` возвращает base64 original_bytes (133MB) — утечка памяти.
|