Files
drhider/History/code-fixes/2026-08-24-v073-security-fixes.md
T

47 lines
3.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# v0.0.73 — фиксы по код-ревью Соннета (безопасность + явные баги) (2026-08-24)
_code-fixes. По ревью `History/sonnet/2026-08-24-code-review-sonnet.md` (промпт `docs/code-review-sonnet.md`)._
_Критично перепроверены в коде; спорные пункты — отклонены/отложены (см. ниже)._
## Исправлено (6 фиксов)
1. **SSRF** (`api_bp.py::upload_refs`) — добавлена валидация `url.startswith(VM_UPLOAD_PREFIX)`;
недоверенный URL пропускается. Константа `VM_UPLOAD_PREFIX = "https://contracts.kube5s.ru/drhider-upload/"`.
2. **Path traversal / zip slip** (`api_bp.py`) — функция `_safe_name()`: нормализует слэши,
отбрасывает `..` и абсолютные пути, сохраняя подпапки (`Подпапка/Акт.txt` → как есть,
`../../evil.pdf` → ""). Применена в `upload` и `upload_refs`.
Unit-тест 8 кейсов — все OK.
3. **Слабый SID** (`session.py`) — `uuid.uuid4().hex[:12]``uuid.uuid4().hex` (128 бит).
4. **Серверная ошибка не отображалась** — серверное событие `event: error` (конфликт с встроенным
EventSource) → `event: proc_error`; добавлен клиентский `addEventListener('proc_error', …)`
с показом сообщения.
5. **ZIP-бомба: обход через поддельный `file_size`** (`extractor.py`) — добавлена проверка
`total_uncompressed > MAX_UNCOMPRESSED` ПОСЛЕ `zf.read()` с `break` (ранний выход).
6. **Self-XSS через имя файла** (`index.html`) — добавлена `esc()` и применена к `f.name`
в `rr()` и `procRow()`.
## Отклонено (критично к Соннету)
- **«cleanup(sid) после /download»** — НЕ сделано: ZIP и CSV скачиваются РАЗДЕЛЬНЫМИ запросами;
удаление сессии после отдачи ZIP сломало бы скачивание CSV. Сессия и так чистится по TTL (30 мин).
## Отложено (требуют решения/риск)
- idx-мисматч при `expand_zips` (фильтр расширений на бэке) — связано с фичей v0.0.69
(zip без документов «как есть»), требует решения по поведению.
- Отмена не проверяется в extract-фазе (.doc liberta 120с) — отдельный фикс.
- LLM-таймаут тихо обнуляет чанк — логирование/статус.
- Debug-эндпоинт `session_files` — ограничить/закрыть.
- LLM prompt injection — задокументировать (класс риска, не фикс кода).
## Проверка
- `py_compile` (app.py, api_bp.py, session.py, extractor.py) — OK; `node --check` — OK.
- `_safe_name` unit-тест — 8/8 OK.
- `create_app()` стартует (VERSION 0.0.73).
- Версия 0.0.72 → 0.0.73.
## Проверка на проде (редеплой 20:00, v0.0.73)
- SSRF: `POST /api/upload_refs` с `url=http://169.254.169.254/...``{"count":0,"ok":true}` (URL отклонён).
- Path traversal: `name="../../evil.txt"``{"count":0,"ok":true}` (имя отклонено).
- SID теперь полный 32 hex (128 бит) — виден в ответе.
- Регресс: папка с подпапкой + кириллицей → «Обработано 2 файлов: 4.3с»,
в ZIP `Подпапка/Договор_1.md` + `Акт.md` (пути сохранены, `_safe_name` не сломал подпапки).