Files
elmer/doc/audit-2026-06-07.md

6.9 KiB
Raw Permalink Blame History

Отчёт об аудите (07.06.2026)

Найдено

🔴 Критичные

  1. Краш при отсутствии Bluetooth

    • Файл: android/app/src/main/java/ru/elmer/client/ui/MainActivity.kt
    • Строки: 155, 230, 310
    • Описание: Используется оператор !! для btAdapter. На устройствах без Bluetooth (или в эмуляторе) приложение упадёт при попытке проверить прибор или запустить сканирование.
    • Как исправить: Добавить проверку if (btAdapter == null) перед использованием и выводить сообщение об ошибке.
  2. Отсутствие аутентификации на сервере

    • Файл: api/routes.py
    • Описание: Эндпоинты /api/v1/session/upload, /api/v1/chat и /api/v1/ping-llm принимают запросы без проверки API-ключа. Клиент передаёт X-Api-Key, но сервер его игнорирует. Любой может отправлять запросы и тратить токены LLM.
    • Как исправить: Добавить декоратор @api_key_required или проверку заголовка в before_request.
  3. Состязание потоков (Race Condition) в ScriptRunnerService

    • Файл: android/app/src/main/java/ru/elmer/client/script/ScriptRunnerService.kt
    • Описание: onStartCommand не проверяет, запущен ли уже процесс. Если дважды вызвать startForegroundService (нажав кнопку несколько раз), создадутся два конкурирующих потока ScriptRunner, которые будут одновременно работать с одним и тем же Bluetooth-сокетом.
    • Как исправить: В startRun проверять флаг running и игнорировать повторные запуски.
  4. Логическая ошибка в выборе Bluetooth-устройства

    • Файл: android/app/src/main/java/ru/elmer/client/ui/MainActivity.kt
    • Описание: Функция findElmDevice() при наличии двух и более устройств показывает диалог, но возвращает null немедленно. Стейт-машина (checkElm, scanDtc) видит null и прерывает работу с ошибкой «ELM не найден».
    • Как исправить: Перестроить логику: диалог выбора должен вызываться отдельно, сохранять elmDevice, и только потом запускать операции.

🟡 Средние

  1. Утечка памяти в ElmChecker

    • Файл: android/app/src/main/java/ru/elmer/client/elm/ElmChecker.kt
    • Описание: Список logLines является членом класса. В MainActivity экземпляр elmChecker переиспользуется. Приложение копит логи всех операций в памяти до своей гибели.
    • Как исправить: Очищать logLines в начале каждой операции или переносить лог в локальную переменную метода run().
  2. Утечка курсоров в БД

    • Файл: android/app/src/main/java/ru/elmer/client/db/SessionDb.kt
    • Описание: Методы getResponses, getSessions, getPendingSessions вызывают cursor.close() в конце цикла, но не в finally. При ошибке чтения курсор останется открытым.
    • Как исправить: Использовать конструкцию .use { ... } (в Kotlin для Cursor доступно начиная с определенных версий) или try { ... } finally { cursor.close() }.
  3. Не включены Foreign Keys

    • Файл: android/app/src/main/java/ru/elmer/client/db/SessionDb.kt
    • Описание: Несмотря на наличие REFERENCES sessions(id), SQLite в Android по умолчанию не проверяет целостность связей.
    • Как исправить: Добавить db.setForeignKeyConstraintsEnabled(true) в onConfigure.
  4. Слепой выбор устройства в сервисе

    • Файл: android/app/src/main/java/ru/elmer/client/script/ScriptRunnerService.kt
    • Описание: Сервис берёт bonded[0] — первое попавшееся сопряжённое устройство. Это могут быть наушники или магнитола.
    • Как исправить: Передавать MAC-адрес выбранного ELM через Intent.
  5. Отсутствие лимита на размер запроса

    • Файл: api/routes.py
    • Описание: Сервер принимает список responses любого размера. Злоумышленник может отправить миллион строк, вызвав OOM или переполнение диска логами.
    • Как исправить: Проверять len(responses) перед обработкой.

🟢 Косметика

  1. Неиспользуемые переменные

    • В ElmProtocol.kt константа INIT_TIMEOUT и другие не используются.
    • В MainActivity.kt список chatHistory хранится в памяти, но не восстанавливается после onSaveInstanceState.
  2. Устаревший API

    • BluetoothAdapter.getDefaultAdapter() помечен как Deprecated. В современных Android рекомендуется использовать BluetoothManager.
  3. Бесполезный пинг LLM

    • Эндпоинт /api/v1/ping-llm делает реальный diagnose, что стоит денег (токенов). Кэш есть, но при перезапуске сервера или по таймауту он всё равно будет жечь токены на "пустые" проверки.