Аудит безопасности Laravel CRM: 16 найденных проблем и адресные исправления
В моей практике повторная проверка Laravel CRM показала, почему поверхностного аудита недостаточно. После первых исправлений оставались нарушения границ доступа, проблемы импорта и экспорта, обработки документов и серверного доступа. Ниже — обезличенный кейс с подтверждёнными результатами и остаточными рисками.

Задача и охват
Исходный стек: Laravel 12, PHP 8.2, MySQL, Redis и очереди. Мною проверены маршруты, контроллеры, модели, миграции и фактическая схема БД; отдельно — policies/middleware, формы и API, импорты/экспорты, документы, фоновые задачи, зависимости и инфраструктура.
Метод — обнаружить, ограничить scope, проверить доказательства и описать риск. Вывод связывался с фактическим поведением, исходным кодом, схемой БД или конфигурацией; сам перечень потенциально опасных конструкций не считался готовым finding.
Приоритеты повторного аудита
P1 — 8 проблем
Сначала — риски раскрытия данных, небезопасного вывода, потери документов и серверного доступа.
P2 — 6 проблем
Следующий этап — внутренние поля, управление доступом, очередь, конфигурация и эксплуатационная устойчивость.
P3 — 2 проблемы
Плановые исправления воспроизводимости схемы и дублирующих определений.
P0 — 0
На момент этой проверки находок такого приоритета не зафиксировано. Это не гарантия отсутствия неизвестных рисков.
Основные классы проблем и исправления
Разграничение доступа
Связанные записи ограничены владельцем и направлением; ответы минимизированы. Policies и видимый scope защищают работу с заявками и документами.
Массовый импорт
Подтверждение импорта опирается на сохранённое проверенное состояние, ограничения и одноразовый идентификатор. Произвольный клиентский payload больше не заменяет результат валидации.
Stored XSS и XLSX
Пользовательские данные выводятся безопасно; строки экспорта принудительно сохраняются как текст, а не исполняемые формулы.
Документы и очередь
Неуспешная обработка не считается успехом. Добавлены повторные попытки и сохранение исходника при ошибке.
Секреты и конфигурация
Служебные значения исключены из JSON и сериализуемых заданий; runtime получает конфигурацию на этапе исполнения.
SSH и сеть
Парольный SSH-вход отключён, firewall ограничивает входящий доступ. Согласованное исключение для root key-only зафиксировано отдельно.
Защита документов
Наружу выдаются непрозрачные ссылки со случайным идентификатором. Получение файла требует входа и проверки прав на конкретную заявку; реальные пути и исходные имена хранения не раскрываются.
Для ранее выданных ссылок сохранён безопасный переход на новый адрес, если документ существует и доступ разрешён. Некорректные запросы отклоняются без раскрытия расположения файла.
Что подтверждено проверками
- На первом этапе, до удаления dev-зависимостей: 32 unit-теста и 89 assertions — успешно. Это не полный регрессионный набор для всех последующих 16 находок.
- Проверка синтаксиса изменённых PHP/Blade-файлов и production Vite build — успешно.
- На дату соответствующих проверок Composer audit и npm audit не показывали advisories в проверенном составе зависимостей.
- В целевой runtime-проверке XLSX пользовательская строка записывается как текст.
- При контролируемой ошибке обработки документа задача попала в failed_jobs, исходный файл сохранён.
- В повторном read-only проходе production автотесты не запускались: dev-зависимости были удалены; полный authenticated smoke по всем ролям оставался ограничением.
Исправлено и исключено — разные статусы
По таблице повторного отчёта 13 пунктов закрыты, один закрыт с согласованным исключением, два исключены заказчиком. Исправления приложения применены; это отдельная работа от кейса Docker/PHP, где deploy не выполнялся.
- Исключено заказчиком: очистка секретов и дампов из Git-истории. Удаление из актуального дерева не очищает предыдущие версии.
- Исключено заказчиком: обновление ОС и системных пакетов. Этот остаточный риск не выдаётся за устранённый.
- Согласованное исключение: административный root-доступ сохранён только по ключу.
- Ротация исторических секретов и полная проверка ролей требуют отдельного подтверждения; в этом кейсе они не заявлены завершёнными.
Ограничения и результат
Мой результат — подтверждённый список рисков, адресные исправления и явные исключения. Находки включали не только уязвимости, но и эксплуатационные дефекты, влияющие на надёжность и данные. Все 16 пунктов нельзя называть полностью устранёнными.
Во время одного из этапов установки зависимостей возник кратковременный ответ 500 из-за незавершённой генерации autoload; после завершения установки проверка входа вернула 200. Поэтому этому кейсу не приписывается бесшовный deploy без ошибок.
Публичное описание не содержит маршрутов эксплуатации, данных клиента, адресов сервера и секретов.
Частые вопросы
Все 16 проблем исправлены?
Нет. В отчёте разделены закрытые пункты, согласованное исключение и два исключённых заказчиком направления: Git-история и обновление ОС.
Можно ли ограничиться Composer audit?
Нет. Нарушения границ доступа, импорта, вывода и логики очередей не сводятся к списку известных уязвимостей пакетов.
