DrHider — ревью Opus'а и исправления (2026-06-29)
Контекст
DrHider — сервис обфускации документов. Изначально впихнут в convert_server.py (общий сервер сверки договоров). Сервер падал из-за отсутствия БД → 502. Вынесен в standalone drhider_server.py на порту 8767.
Найденные баги (Opus)
CRITICAL
| # |
Что |
Где |
Исправлено |
| C1 |
Path traversal: /static/../etc/passwd читает любой файл на ВМ |
convert_server.py:_handle_app_js |
✅ os.path.realpath + проверка startswith(base) + whitelist .js/.svg |
HIGH
| # |
Что |
Где |
Исправлено |
| H1 |
Нет лимита размера тела → memory DoS → OOM-kill |
drhider_server.py:_handle_drhider |
✅ MAX_BODY = 200MB, 413 при превышении |
| H2 |
DrHider дублирован в convert_server.py (БД-зависимом) |
convert_server.py |
✅ Удалён роут /api/drhider и метод _handle_drhider |
MEDIUM
| # |
Что |
Где |
Исправлено |
| M1 |
generate_passport: re.match().group(0) → AttributeError если LLM вернёт не «паспорт» |
drhider.py |
✅ m.group(0) if m else "" |
| M2 |
Замена по подстроке без границ слова |
drhider.py |
⬜ отложено |
| M3 |
Три разных версии: 1.0, 1.2, v1.3 |
все файлы |
✅ везде 1.3 |
LOW
| # |
Что |
Где |
Исправлено |
| L1 |
Мусорные импорты: io as io_mod, hashlib, дубль import cgi |
все файлы |
✅ удалены |
| L2 |
sorted_keys пересчитывается на каждый абзац docx |
drhider.py |
⬜ отложено |
| L3 |
CORS * на эндпоинте обфускации |
оба сервера |
⬜ отложено |
| L4 |
Утечка временных файлов в _handle_convert_doc |
convert_server.py |
⬜ отложено |
Версии после исправлений
DRHIDER_VERSION = "1.3" (drhider.py)
DRHIDER_SERVER_VERSION = "1.3" (drhider_server.py)
v1.3 (drhider.html)
Архитектура (после исправлений)
:8766 — convert_server.py (сверка договоров, с БД или без)
:8767 — drhider_server.py (только обфускация, БД не нужна)
- nginx:
/api/drhider → :8767, остальные /api/* → :8766
- systemd:
contracts.service + contracts-drhider.service