Files
drhider/History/sonnet/2026-08-24-code-review-sonnet.md
T

4.5 KiB
Raw Blame History

Код-ревью DrHider — ответ Соннета (2026-08-24)

sonnet. Промпт: docs/code-review-sonnet.md (12 файлов кода, 8 вопросов). Ревью по v0.0.72. Ничего не исправлено — только задокументировано.

🔴 Критичные

Баг Файл ~строка Суть Фикс
SSRF api_bp.py upload_refs ~93 url из клиентского JSON без валидации → httpx.stream("GET", url) + follow_redirects=True. Доступ к metadata/kube-apiserver валидировать URL-prefix == VM_UPLOAD_URL до запроса
Path traversal / zip slip api_bp.py + builder.py ~88, ~55 name = ref.get("name") без санитизации → ../../evil.md в выходном ZIP name = os.path.basename(ref.get("name",""))

🟠 Средние

Баг Файл ~строка Суть
Серверная ошибка не отображается api_bp.py + index.html ~388, ~840 сервер шлёт event: error — это встроенное имя EventSource; клиент не слушает кастомное → «SSE connection failed» вместо реального msg. Переименовать в proc_error
idx-мисматч при expand_zips на бэке obfuscator.py + index.html ~90, sendIdx фронт фильтрует zip по .pdf/.doc/.docx/.txt/.md, бэк расширяет ВСЕ файлы → число/порядок не совпадает → sendIdx[idx]=undefined
Слабый SID (48 бит) session.py 85 uuid4().hex[:12]; убрать [:12] → 128 бит
ZIP-бомба: обход через поддельный file_size extractor.py ~240 лимит проверяется по info.file_size (central dir, подделывается) ДО чтения; проверять ПОСЛЕ zf.read()
Неатомарность pull при ошибке api_bp.py upload_refs ~115 при исчерпании ретраев 502 БЕЗ session_id; частичная сессия-сирота до TTL

🟡 Мелкие

Баг Файл ~строка Суть
Отмена не работает в extract-фазе obfuscator.py ~130 в extract-цикле нет cancel_event.is_set(); .doc (liberta 120с) → отмена ждёт все извлечения
TOCTOU: сессия между check и pause_ttl api_bp.py ~165-171 get_files (lock снят) → pause_ttl; маловероятно
fileTimers не заполняется index.html ~792 мёртвый код, fallback всегда 0.0с
Self-XSS: f.name в innerHTML index.html ~280, ~380 имя файла без escaping → textContent/escapeHtml()
ZIP с non-doc расширениями → мусор extractor.py ~257 фильтровать расширения в expand_zips
Сессия не чистится после /download api_bp.py ~430 500МБ висит 30 мин → OOM; cleanup(sid)
LLM-таймаут тихо обнуляет чанк llm_client.py + scanner.py ~70, ~220 except → return [], PII не найден без предупреждения
Debug-эндпоинт session_files api_bp.py ~139 список файлов любой сессии по SID без токена
LLM prompt injection scanner.py ~200 текст документа дословно в prompt → подавление NER

Подтверждено корректным (Соннет)

  • Различимость «сессия не найдена» vs «лимит» ✓
  • Гонок на cancel_event/queue нет (thread-safe) ✓
  • Утечек httpx/zipfile/EventSource/таймеров нет ✓
  • Пустой txt, битый pdf, 0 файлов/все сверх лимита — обрабатываются ✓

Что уже исправлено ранее (до этого ревью)

  • Ретраи pull (v0.0.72) — Соннет отметил остаточную неатомарность.
  • Разделение статусов «пропущен (лимит)» / «не извлечён» (v0.0.71).
  • Счётчик дедупа (v0.0.72).

TODO-связь

  • Открытый баг кнопки «Обфусцировать» при 0 файлов — docs/WhatTODO.md (не покрыт ревью Соннета).