Параметр forbidNonWhitelisted

Параметр forbidNonWhitelisted применяется в механизме валидации объектов, когда входные данные проходят проверку через схемы, описанные с помощью декораторов class-validator. Он используется в связке с преобразованием и фильтрацией входящих данных и играет ключевую роль в защите приложения от «лишних» или неожиданных полей.

В типичном сценарии обработки входных данных система принимает объект, преобразует его в экземпляр класса и затем проверяет соответствие правилам, заданным через декораторы (@IsString, @IsNumber, @IsOptional и т.д.). Однако даже при наличии строгой валидации объект может содержать дополнительные поля, не описанные в DTO. Именно здесь вступает в работу механизм whitelist и параметр, который управляет его строгим поведением.


Механизм whitelist отвечает за удаление всех свойств объекта, которые не описаны в классе-валидаторе. То есть если входящий объект содержит поля, отсутствующие в DTO, они автоматически отбрасываются до этапа валидации.

Однако существует два варианта поведения:

  • мягкий режим: лишние поля просто удаляются
  • строгий режим: наличие лишних полей приводит к ошибке

За строгий режим отвечает параметр forbidNonWhitelisted.


Основная логика работы

При включённом whitelist и активированном forbidNonWhitelisted процесс обработки входных данных выглядит следующим образом:

  1. Входящий объект преобразуется в экземпляр DTO-класса.
  2. Выполняется проверка всех полей, описанных в классе.
  3. Выполняется проверка наличия дополнительных полей.
  4. Если обнаружены поля, отсутствующие в DTO, выбрасывается исключение.
  5. Объект не проходит дальше по цепочке обработки запроса.

Таким образом, forbidNonWhitelisted не просто фильтрует данные, а полностью блокирует запрос при нарушении схемы.


Поведение без forbidNonWhitelisted

Если whitelist включён, но forbidNonWhitelisted не активирован, происходит более мягкая обработка:

  • все неизвестные поля удаляются
  • валидация проходит только по определённым свойствам
  • запрос считается валидным, если остальные правила соблюдены

Такой режим подходит для ситуаций, где допустима «гибкость» входных данных, но не требуется строгая фиксация структуры.


Разница между фильтрацией и строгой валидацией

Ключевая концептуальная разница заключается в реакции системы на «лишние» данные:

Режим Поведение
whitelist без forbidNonWhitelisted удаление лишних полей
whitelist + forbidNonWhitelisted ошибка при наличии лишних полей
без whitelist лишние поля игнорируются валидацией

Типичный сценарий использования

Строгий режим особенно важен в API, где структура входных данных должна быть жёстко фиксирована. Например:

  • авторизация и регистрация пользователей
  • финансовые операции
  • административные операции
  • публичные API с контрактами

В таких случаях любые дополнительные поля могут свидетельствовать о:

  • ошибке клиента
  • попытке подмены данных
  • некорректной интеграции
  • потенциальной атаке

Пример поведения на уровне DTO

import { IsString, IsNumber } from 'class-validator';

export class CreateUserDto {
  @IsString()
  name: string;

  @IsNumber()
  age: number;
}

Входящий объект:

{
  "name": "Alex",
  "age": 25,
  "role": "admin"
}

При активированном whitelist: true и forbidNonWhitelisted: true поле role приведёт к ошибке, поскольку оно не описано в DTO.


Механика исключения

При обнаружении неразрешённых полей система выбрасывает исключение уровня валидации. В контексте серверных фреймворков это обычно преобразуется в HTTP-ошибку с кодом 400.

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


Влияние на безопасность приложения

Использование forbidNonWhitelisted повышает устойчивость API к следующим классам проблем:

  • скрытая передача несанкционированных параметров
  • попытки изменения поведения через дополнительные поля
  • атаки, использующие «массовое присваивание» (mass assignment)
  • несоответствие контрактов между клиентом и сервером

Особенно критично это в системах, где входной объект напрямую используется для создания или обновления сущностей в базе данных.


Взаимодействие с transform

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

Без преобразования часть механизмов может работать некорректно, так как входной объект остаётся простым JSON и не имеет метаданных класса.


Сценарии ложных срабатываний

Несмотря на полезность строгого режима, он может приводить к нежелательным ситуациям:

  • клиент отправляет дополнительные поля для обратной совместимости
  • разные версии API используют разные схемы DTO
  • промежуточные сервисы добавляют технические поля

В таких случаях включение forbidNonWhitelisted требует строгого контроля версий и контрактов.


Поведение в сложных структурах

При работе с вложенными объектами правило применяется рекурсивно. Если DTO содержит вложенные классы, каждый уровень проходит проверку на наличие неизвестных полей.

Это означает, что даже корректный внешний объект может быть отклонён из-за лишних данных внутри вложенных структур.


Практическая интерпретация в архитектуре API

Использование forbidNonWhitelisted фактически означает переход от модели «гибкого JSON» к модели «контрактных структур». API перестаёт быть tolerant к изменениям входных данных и требует строгого соответствия схемам.

Такой подход часто используется в системах, где:

  • важна предсказуемость поведения
  • критична целостность данных
  • требуется строгая типизация на границе системы
  • необходимо минимизировать поверхность атаки