Если достаточно заменить comment_id в запросе, чтобы изменить чужой комментарий, интерфейс скрывает кнопку, но backend не проверяет право на конкретный объект. Это классическая ошибка объектной авторизации: аутентификация пользователя есть, а связь пользователя с ресурсом не подтверждается.

Исправление выполняется на сервере. Комментарий нужно выбирать внутри разрешенной области пользователя или tenant, затем проверять роль, владельца и состояние объекта. Клиентский user_id и скрытая кнопка не являются доказательством права.

Что проверить в первую очередь

Сначала зафиксируйте точный сценарий, время ошибки и последнее известное рабочее состояние. Не меняйте несколько настроек одновременно: один контролируемый шаг должен подтверждать или исключать одну гипотезу. Перед работой с данными и конфигурацией подготовьте резервную копию и понятный способ отката.

  • Снимите запрос редактирования и определите, какие идентификаторы принимает backend.
  • Проверьте, может ли обычный пользователь изменить comment_id, author_id или tenant_id.
  • Составьте матрицу прав: автор, модератор, администратор, удаленный и заблокированный комментарий.
  • Проверьте REST, GraphQL, мобильный API и старые endpoint отдельно.

Почему возникает проблема

Внешний симптом обычно появляется на границе нескольких компонентов: интерфейса, backend, базы, фоновой очереди или внешнего сервиса. Поэтому важно найти первое место, где состояние становится неверным, а не исправлять последнее сообщение об ошибке.

  • Backend выполняет UPDATE WHERE id=:id без условия owner/tenant.
  • author_id принимается из тела запроса и не сверяется с текущей сессией.
  • Администраторская проверка роли ошибочно срабатывает для любого авторизованного пользователя.
  • Кеш решения доступа не включает user/tenant и переиспользуется между клиентами.
  • Один endpoint защищен, а массовое редактирование или GraphQL mutation — нет.

Пошаговая диагностика

Диагностику проводите на тестовой записи или отдельном окружении. В журналах скрывайте токены, пароли и персональные данные. Для каждого шага сохраняйте измеримый результат: идентификатор события, код ответа, версию записи, состояние процесса или контрольную сумму.

  • Создайте двух тестовых пользователей и комментарии в разных tenant.
  • Попробуйте чтение, изменение, удаление и восстановление чужого объекта каждым маршрутом.
  • Проверьте ORM scope и SQL, сформированный для обычного пользователя.
  • Повторите тест после смены роли и выхода, исключая устаревший кеш прав.
  • Проверьте audit log: он должен фиксировать actor и target, но не содержать лишний текст.

Объектная авторизация на стороне сервера

Правильная проверка отвечает не только на вопрос «кто вошел», но и «может ли этот субъект выполнить это действие над этим конкретным объектом сейчас».

  • Обычный пользователь получает объект запросом WHERE id=? AND author_id=? AND tenant_id=?.
  • Модератор проходит отдельную policy с ограниченной областью сообщества или проекта.
  • Администраторское право не выводится из параметра запроса и проверяется по серверной роли.
  • Удаленное, закрытое или архивное состояние может запрещать редактирование даже владельцу.
  • Решение доступа вычисляется заново для операции изменения и не доверяет предыдущему чтению.

Как исправить проблему

Исправление лучше разбить на небольшие обратимые изменения. Сначала устраните подтвержденную причину, затем повторите исходный сценарий и проверьте соседние функции. Массовую обработку данных запускайте на ограниченной выборке с отчетом и только после сверки расширяйте на весь объем.

  • Вынесите правила в policy/authorization service и примените ко всем операциям.
  • Фильтруйте выборку по текущему user и tenant до выполнения UPDATE.
  • Игнорируйте author_id из клиента при обычном редактировании.
  • Исправьте ключ кеша прав или не кешируйте чувствительное решение без строгого контекста.
  • Добавьте единый ответ 404/403 согласно модели раскрытия существования объекта.

Безопасный порядок внедрения

  • Сохраните затрагиваемые данные, конфигурацию и текущие журналы, заранее проверив способ отката.
  • Повторите проблему на тестовом объекте без реальных списаний, рассылок и изменений клиентских данных.
  • Внесите одно логическое изменение и зафиксируйте его в системе контроля версий или журнале работ.
  • Не отключайте авторизацию, валидацию, шифрование и другие защитные механизмы ради быстрого исчезновения ошибки.
  • После выкладки контролируйте логи, метрики и полный пользовательский сценарий, а не только один успешный запрос.

Как проверить результат

Разовый успешный тест недостаточен. Повторите операцию, проверьте крайние значения, параллельные действия и восстановление после перезапуска или временного сбоя. Для важного сценария сохраните автоматический тест либо короткий регрессионный чек-лист.

  • Автор редактирует свой комментарий, но не чужой даже при подмене ID.
  • Модератор действует только в разрешенной области, а пользователь другого tenant не видит объект.
  • Массовый endpoint и GraphQL mutation подчиняются тем же policy.
  • После смены роли старый токен или кеш не сохраняет прежние привилегии.

Типичные ошибки при исправлении

  • Исправлять только отображение кнопки во frontend.
  • Сравнивать owner с user_id, присланным самим клиентом.
  • Выдавать подробный чужой объект до проверки права.
  • Проверять право только при чтении, но не при update/delete.

Как предотвратить повторение

Профилактика строится вокруг явных контрактов, повторяемых релизов и наблюдаемости. Система должна не только работать сейчас, но и позволять быстро увидеть нарушение инварианта при следующем обновлении, росте нагрузки или сбое внешнего сервиса.

  • Создайте матрицу ролей и негативные integration-тесты для каждого объекта.
  • Используйте scoped repositories, которые требуют actor/tenant.
  • Проводите code review всех endpoint с прямым ID ресурса.
  • Мониторьте необычные последовательные обращения к множеству чужих ID.

Что подготовить для технического разбора

  • Описание ожидаемого и фактического поведения, а также точную последовательность действий.
  • Время проблемы, идентификатор тестового объекта и версии затронутых компонентов.
  • Фрагменты журналов до и после ошибки без секретов и персональных данных.
  • Перечень последних изменений и уже выполненных проверок.
  • Безопасный доступ к тестовой среде или способ воспроизвести сбой без влияния на клиентов.

Частые вопросы

Что лучше возвращать: 403 или 404?

Оба варианта возможны. 404 уменьшает раскрытие существования чужого объекта, 403 явно сообщает о запрете. Важно выбрать последовательную модель.

Достаточно ли UUID вместо числового ID?

Нет. Непредсказуемый ID усложняет перебор, но не заменяет проверку права на объект.

Когда нужна помощь специалиста

Если в API можно менять чужие комментарии или другие записи подменой ID, я могу проверить объектную авторизацию, исправить policy и добавить негативные тесты для ролей, tenant и альтернативных endpoint.