Real-Time Backend

Input Validation

В 2017 году Equifax потерял данные 147 млн человек из-за необработанного входного параметра. В контексте WebSocket один невалидный payload может вызвать crash всего Node.js процесса - и всех подключённых клиентов вместе с ним.

  • **Stripe** использует Zod для валидации всех входящих webhook-событий в production; типизация из схемы используется напрямую в TypeScript коде без дублирования типов.
  • **Discord** ограничивает сообщения до 2000 символов и валидирует все gateway events через строгую схему; нарушение протокола - immediate disconnect с кодом 4000.
  • **Slack** применяет многоуровневую валидацию: API gateway проверяет размер и rate limit, application layer проверяет схему, бизнес-слой проверяет права доступа к channel.

Schema Validation

Schema validation - проверка структуры входящего сообщения до передачи в бизнес-логику. WebSocket принимает произвольные строки: без валидации один невалидный payload может вызвать uncaught exception и упасть весь процесс Node.js. Stripe использует Zod для runtime-валидации всех входящих webhook-событий; Discord валидирует каждый gateway event перед диспатчем.

Discriminated union по полю type - лучшая практика для WebSocket-протоколов: каждый тип события имеет строго типизированный payload. Это также документация протокола: схема Zod одновременно является runtime-validator и TypeScript-типом.

Клиент отправляет сообщение: `{"type": "chat", "roomId": "not-a-uuid", "content": "hello", "timestamp": 1700000000}`. ChatMessageSchema требует roomId: z.string().uuid(). Что произойдёт при safeParse?

Sanitization

Sanitization - очистка данных от потенциально вредоносных конструкций после прохождения schema validation. Даже валидный по схеме текст может содержать XSS-payload, SQL-инъекцию или управляющие символы. WebSocket-приложение, передающее пользовательские сообщения другим клиентам без sanitization, создаёт stored XSS вектор.

Sanitization на сервере обязательна даже если фронтенд тоже sanitize - клиент не контролируется разработчиком. Любой может подключиться к WebSocket-эндпоинту напрямую через curl или скрипт и обойти frontend-валидацию.

Чат-приложение передаёт сообщения между клиентами. Frontend рендерит контент через `element.textContent = message` (не innerHTML). Нужна ли server-side sanitization от XSS?

Size Limits

Ограничение размера входящих сообщений защищает от нескольких векторов: memory exhaustion (один payload 100 MB занимает RAM на время обработки), JSON parsing DoS (специально constructed JSON O(n^2) при парсинге), и backpressure на downstream сервисы. ws библиотека для Node.js позволяет задать maxPayload при инициализации.

Discord устанавливает лимит 2000 символов на сообщение в чате - это не только UX-решение, но и защита от payload attacks. Telegram позволяет 4096 символов. Slack API ограничивает block kit payload до 3000 блоков. Лимиты должны быть согласованы между ws-сервером, API gateway и схемой БД.

WebSocketServer инициализирован с maxPayload: 65536 (64 KB). Клиент отправляет фрейм размером 70 KB. Что произойдёт?

Validation Patterns

Комплексная валидация строится послойно: сетевой уровень (maxPayload, rate limit), JSON parsing (try/catch + depth check), schema validation (Zod discriminated union), бизнес-правила (roomId существует, пользователь имеет доступ), sanitization (XSS, управляющие символы). Каждый слой отвечает за свою часть и не дублирует другие.

Validation pipeline возвращает типизированные error codes - это позволяет клиенту корректно обработать каждый тип ошибки: показать 'invalid format' vs 'no access' vs 'server error'. Не возвращать стек-трейс или детали реализации в error response - это information leakage.

Frontend-валидация защищает сервер - если данные прошли проверку на клиенте, они безопасны

Frontend-валидация улучшает UX, но не обеспечивает безопасность - любой может отправить сырой запрос напрямую к WebSocket-эндпоинту

WebSocket endpoint доступен через curl, Postman, или custom скрипт. Frontend код выполняется на устройстве пользователя и полностью подконтролен атакующему.

API возвращает клиенту ошибку: `{"error": "Column 'userId' doesn't exist in table 'users'"}`. Какую проблему безопасности это создаёт?

Итоги

  • **Schema validation** (Zod discriminated union) - первая остановка для входящих данных: структура, типы, форматы - до любой бизнес-логики.
  • **Sanitization** удаляет вредоносные конструкции из валидных по схеме данных; server-side обязательна независимо от frontend-валидации.
  • **Многоуровневый pipeline** (сеть → JSON → схема → бизнес-правила → sanitization) обеспечивает defence in depth - каждый слой отвечает за свою зону ответственности.

Связанные темы

Input validation интегрируется с другими аспектами безопасности real-time систем:

  • DDoS и Abuse — Валидация размера (maxPayload) - первая линия защиты от payload-based DoS атак
  • Encryption — TLS не заменяет валидацию - шифрование скрывает payload при передаче, но не от сервера после расшифровки
  • Audit и Compliance — Логирование validation errors помогает обнаруживать попытки атак и документировать инциденты для compliance

Вопросы для размышления

  • Как организовать версионирование протокола (v1/v2 схем) в WebSocket приложении без breaking changes для существующих клиентов?
  • Где граница между валидацией (технический контракт) и бизнес-правилами (доступ к ресурсам) - и почему важно их разделять в коде?
  • Как тестировать validation pipeline: unit-тесты для схем, fuzzing для парсера, или integration-тесты с реальными WebSocket-соединениями?

Связанные уроки

  • sec-01
Input Validation

0

1

Войти