From d17baa767c3f19912f12f0e65c28a2b191694c7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CNaeel=E2=80=9D?= Date: Tue, 30 Jun 2026 11:25:29 +0400 Subject: [PATCH] =?UTF-8?q?fix:=20audit=20=E2=80=94=20json=20try/except,?= =?UTF-8?q?=20ZIP-bomb=20drhider,=20classify=20reset=20only=20processing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- History/audit-2026-06-30.md | 64 ++++++++++++++++++++++++++++++++++++ architecture-diagram.jpeg | Bin 0 -> 71395 bytes architecture-diagram.png | Bin 0 -> 33498 bytes deploy/convert_server.py | 45 ++++++++++++++++++------- deploy/db/documents.py | 5 +-- deploy/drhider/drhider.py | 22 +++++++++---- 6 files changed, 115 insertions(+), 21 deletions(-) create mode 100644 History/audit-2026-06-30.md create mode 100644 architecture-diagram.jpeg create mode 100644 architecture-diagram.png diff --git a/History/audit-2026-06-30.md b/History/audit-2026-06-30.md new file mode 100644 index 0000000..343c5ec --- /dev/null +++ b/History/audit-2026-06-30.md @@ -0,0 +1,64 @@ +# Аудит кода contracts-flask — 2026-06-30 + +## Контекст + +После переименования `services/` → `compare/` и восстановления сервиса проведён аудит кодовой базы. +Фокус: **что реально упадёт, сломается или работает нестабильно**. Без вылизывания. +Сервис непубличный, дев-окружение. Auth пока не нужен. + +--- + +## ⚠️ Исправлено в этом цикле + +### #1. POST-хендлеры без try вокруг Content-Length и json.loads +**Файл:** `deploy/convert_server.py` +**Проблема:** `_handle_api_sync`, `_handle_api_groups`, `_handle_apply_groups`, промпт-хендлеры — все делают `json.loads(self.rfile.read(length))` без try. Битый Content-Length → ValueError, пустой body → JSONDecodeError. Оба не ловятся → оборванное соединение. +**Фикс:** обёрнуто в try/except с возвратом `{"ok": false, "error": "..."}`. + +### #11. ZIP-бомба в DrHider +**Файл:** `deploy/drhider/drhider.py` +**Проблема:** проверяется только заявленный `info.file_size` (можно подделать), нет лимита фактически распакованных байт, нет проверки ratio сжатия. +**Фикс:** скопирована защита из `compare/unzip.py` — накопительный счётчик распакованных байт + ratio-проверка (100×). + +### #6. classify сбрасывает status у уже классифицированных документов +**Файл:** `deploy/compare/classify.py` +**Проблема:** `reset_classify_status(batch_id)` в начале `classify_batch()` сбрасывает на 'pending' ВСЕ документы батча, включая уже классифицированные. При повторном запуске — жжёт токены LLM на переклассификацию. +**Фикс:** `reset_classify_status` теперь сбрасывает только `'processing'` (crash recovery), оставляя `'classified'` и `'garbage'` нетронутыми. + +--- + +## 🟡 Известные проблемы (не исправлены — низкий приоритет) + +### SSE: двойная запись в мёртвый сокет +`convert_server.py` — при отвале клиента `run_pipeline` бросает `BrokenPipeError`, except ловит и **снова** зовёт `_sse` → второе исключение. Грязные трейсы, но не крашит сервер. + +### classify: «успешный» JSON от LLM, который не dict +`classify.py` — `json.loads` может вернуть список/строку вместо dict → `AttributeError` → документ молча помечается failed. Случается редко. + +### .doc через /upload не работает +`parse.py` зовёт `_parse_docx` (python-docx) для `.doc`, а тот читает только OOXML/.docx. Формат разрешён в `upload.py`, но не парсится. Надо либо убрать `.doc` из whitelist, либо звать `/convert-doc`. + +### Гонка счётчиков в ThreadPoolExecutor +`classify.py` мутирует `garbage`, `json_total`, `type_counts` из 4 потоков через `nonlocal` без локов. Счётчики могут привирать на 1-2 единицы. + +### _safe_json_parse — 4 уровня эвристик +Реаниматор битого JSON. Лечит симптом «LLM обрезал ответ». Дописывание кавычек/скобок вслепую может дать валидный но мусорный JSON → тихая неверная классификация. + +### Весь файл в base64 в БД +`upload.py` хранит `original_bytes` как base64 (+33%) в Postgres. `SELECT *` таскает мегабайты. База пухнет. + +### LLM URL/key захардкожены в 3 местах +`classify.py`, `drhider_server.py`, `llm_client.py`. Рассинхрон — тот же класс проблемы, что с `DB_NAME`. + +### DrHider: PDF→txt + потеря форматирования DOCX +PDF на выходе становится `.txt`. Замена в DOCX сваливает текст в первый run → форматирование плывёт. + +--- + +## ✅ Что НЕ является проблемой (проверено) + +- SQL-инъекций нет — весь `db/` на параметризованных запросах +- Path traversal в static-раздаче прикрыт `realpath`+`startswith` +- Path traversal в ZIP-распаковке прикрыт (`unzip.py`, `drhider.py`) +- Nginx защищает от больших тел (client_max_body_size) +- DrHider двойной encode fix сделан diff --git a/architecture-diagram.jpeg b/architecture-diagram.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..770b15098ed914618cb7d15db390400d1f0ecedc GIT binary patch literal 71395 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 EAG~g${Qv*} literal 0 HcmV?d00001 diff --git a/architecture-diagram.png b/architecture-diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..8bdf0a5daa90a3c36e83f4d73d1287c83c046c2a GIT binary patch literal 33498 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 kD#)N#h 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 0 else {} + body = self._read_json_body() keep_ids = set(body.get("keep_ids", [])) # Prevent DoS: too many IDs if len(keep_ids) > 1000: @@ -283,8 +282,9 @@ class Handler(BaseHTTPRequestHandler): Отдельный процесс — свои коннекты, своя память. HTTP-сервер продолжает отвечать на batch-progress. """ - length = int(self.headers.get("Content-Length", 0)) - body = json.loads(self.rfile.read(length)) + body = self._read_json_body() + if not body: + return batch_id = body.get("batch_id") if not batch_id: self._json({"ok": False, "error": "batch_id required"}, 400) @@ -326,8 +326,9 @@ class Handler(BaseHTTPRequestHandler): # ── POST /apply-groups ─────────────────────────────────────────────── def _handle_apply_groups(self): - length = int(self.headers.get("Content-Length", 0)) - body = json.loads(self.rfile.read(length)) + body = self._read_json_body() + if not body: + return batch_id = body.get("batch_id") groups = body.get("groups", []) if not batch_id: @@ -392,8 +393,9 @@ class Handler(BaseHTTPRequestHandler): def _handle_api_prompts_save(self): from db import prompts as db_p - length = int(self.headers.get("Content-Length", 0)) - body = json.loads(self.rfile.read(length)) + body = self._read_json_body() + if not body: + return role = body.get("role", "") name = body.get("name", "v" + __import__("datetime").datetime.now().isoformat()[:16]) prompt_body = body.get("body", "") @@ -407,8 +409,9 @@ class Handler(BaseHTTPRequestHandler): def _handle_api_prompts_activate(self): from db import prompts as db_p - length = int(self.headers.get("Content-Length", 0)) - body = json.loads(self.rfile.read(length)) + body = self._read_json_body() + if not body: + return pid = body.get("id", "") if not pid: self._json({"ok": False, "error": "id required"}, 400) @@ -418,8 +421,9 @@ class Handler(BaseHTTPRequestHandler): def _handle_api_prompts_delete(self): from db import prompts as db_p - length = int(self.headers.get("Content-Length", 0)) - body = json.loads(self.rfile.read(length)) + body = self._read_json_body() + if not body: + return pid = body.get("id", "") if not pid: self._json({"ok": False, "error": "id required"}, 400) @@ -532,6 +536,23 @@ class Handler(BaseHTTPRequestHandler): # ── Helpers ─────────────────────────────────────────────────────────── + def _read_json_body(self): + """Безопасное чтение JSON из тела POST-запроса. + Возвращает dict или None (если ошибка — уже отправлен 400).""" + try: + length = int(self.headers.get("Content-Length", 0)) + except (ValueError, TypeError): + self._json({"ok": False, "error": "invalid Content-Length"}, 400) + return None + if length == 0: + return {} + try: + raw = self.rfile.read(length) + return json.loads(raw) + except (json.JSONDecodeError, Exception) as e: + self._json({"ok": False, "error": f"invalid JSON: {e}"}, 400) + return None + def _json(self, data, status=200): self.send_response(status) self._send_cors() diff --git a/deploy/db/documents.py b/deploy/db/documents.py index d711689..03a3e85 100644 --- a/deploy/db/documents.py +++ b/deploy/db/documents.py @@ -79,9 +79,10 @@ def list_pending(batch_id): def reset_classify_status(batch_id): - """Сбросить classify_status на 'pending' для всех документов батча (включая 'processing' — crash recovery).""" + """Сбросить classify_status на 'pending' только для 'processing' (crash recovery). + Уже классифицированные ('classified', 'garbage', 'failed') НЕ трогаем.""" return execute( - "UPDATE documents SET classify_status='pending', error_message=NULL WHERE batch_id=%s", + "UPDATE documents SET classify_status='pending', error_message=NULL WHERE batch_id=%s AND classify_status='processing'", (batch_id,), ) diff --git a/deploy/drhider/drhider.py b/deploy/drhider/drhider.py index a1ee671..48aab8b 100644 --- a/deploy/drhider/drhider.py +++ b/deploy/drhider/drhider.py @@ -251,25 +251,29 @@ class TwoPassObfuscator: self._sorted_keys.clear() def _expand_zips(self, files: List[Tuple[str, bytes, str]]) -> List[Tuple[str, bytes, str]]: - """Распаковать ZIP-файлы, заменив их содержимым. Остальные файлы — как есть.""" + """Распаковать ZIP-файлы, заменив их содержимым. Остальные файлы — как есть. + Защита от ZIP-бомб: ratio + накопительный размер (как в compare/unzip.py).""" result = [] for fname, content, ctype in files: if fname.lower().endswith('.zip'): try: with zipfile.ZipFile(io.BytesIO(content)) as zf: - total_size = sum(info.file_size for info in zf.infolist()) - if total_size > 500 * 1024 * 1024: # 500 MB - log.warning("ZIP too large, skipping expansion: %s", fname) - result.append((fname, content, ctype)) - continue if len(zf.infolist()) > 500: log.warning("ZIP too many files, skipping: %s", fname) result.append((fname, content, ctype)) continue + total_uncompressed = 0 for info in zf.infolist(): if info.is_dir(): continue - # cp437 → utf8 (как в services/unzip.py) + # ZIP bomb: ratio check + if info.compress_size > 0: + ratio = info.file_size / info.compress_size + if ratio > 100: + log.warning("ZIP bomb ratio %.0f:1, skipping: %s", ratio, fname) + result.append((fname, content, ctype)) + break + # cp437 → utf8 (как в compare/unzip.py) name = info.filename try: name = name.encode("cp437").decode("utf-8", errors="replace") @@ -280,6 +284,10 @@ class TwoPassObfuscator: if not name or name.endswith("/") or ".." in name or "/" in name or "\\" in name: continue inner_data = zf.read(info) + total_uncompressed += len(inner_data) + if total_uncompressed > 500 * 1024 * 1024: # 500 MB + log.warning("ZIP uncompressed limit exceeded, stopping: %s", fname) + break result.append((name, inner_data, "")) except Exception as e: log.warning("Failed to expand ZIP %s: %s", fname, e)