Защита от инъекций

При работе с Universal Router в JavaScript критически важно учитывать, что маршруты могут принимать динамические параметры из URL. Любой входной параметр, не прошедший валидацию, потенциально может быть использован для атаки через инъекции. В контексте маршрутизации это чаще всего проявляется в виде попыток изменения логики приложения через специально сформированные URL-параметры.

Ключевой принцип: никогда не доверять данным, полученным из URL. Любой параметр должен проходить строгую проверку перед использованием.


Валидация параметров маршрутов

Universal Router позволяет определять маршруты с динамическими сегментами:

const routes = [
  {
    path: '/user/:id',
    action: ({ params }) => {
      return fetchUserById(params.id);
    }
  }
];

В этом примере params.id может содержать любой текст, введённый пользователем. Если сразу передавать его в SQL-запрос или в вызов функций без проверки, появляется уязвимость. Для защиты необходимо использовать:

  1. Проверку типов и формата Для числовых идентификаторов:

    const userId = parseInt(params.id, 10);
    if (isNaN(userId)) throw new Error('Неверный ID пользователя');
  2. Ограничение длины строки Для текстовых параметров стоит использовать ограничение по количеству символов:

    if (params.name.length > 50) throw new Error('Имя слишком длинное');
  3. Белые списки допустимых значений Если маршрут принимает конкретные значения:

    const allowedRoles = ['admin', 'editor', 'viewer'];
    if (!allowedRoles.includes(params.role)) throw new Error('Недопустимая роль');

Экранирование данных при передаче

В Universal Router часто динамические параметры используются для рендеринга контента. В этом случае критически важно предотвращать внедрение вредоносного HTML или скриптов:

function escapeHtml(str) {
  return str
    .replace(/&/g, "&")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;")
    .replace(/"/g, "&quot;")
    .replace(/'/g, "&#039;");
}

const routes = [
  {
    path: '/greet/:name',
    action: ({ params }) => {
      const safeName = escapeHtml(params.name);
      return `<h1>Привет, ${safeName}</h1>`;
    }
  }
];

Это гарантирует, что даже если в params.name будет вставлен скрипт, он не выполнится.


Защита маршрутов с асинхронными действиями

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

const routes = [
  {
    path: '/search/:query',
    async action({ params }) {
      const query = params.query.trim();
      if (query.length > 100) throw new Error('Запрос слишком длинный');

      // Пример использования безопасного параметра
      return fetch(`/api/search?q=${encodeURIComponent(query)}`)
        .then(res => res.json());
    }
  }
];

Использование encodeURIComponent предотвращает вмешательство специальных символов в URL и защитит от атак типа URL-инъекции.


Ограничение глубины вложенных маршрутов

Сложные вложенные маршруты повышают риск обхода валидации и внедрения нежелательных действий. В Universal Router следует:

  • Ограничивать количество вложенных маршрутов, особенно если они используют динамические сегменты.
  • На каждом уровне проверять параметры и использовать строгие шаблоны:
const routes = [
  {
    path: '/admin/:section',
    children: [
      { path: 'users', action: () => loadUsers() },
      { path: 'settings', action: () => loadSettings() }
    ],
    action: ({ params }) => {
      const allowedSections = ['users', 'settings'];
      if (!allowedSections.includes(params.section)) throw new Error('Недопустимый раздел');
    }
  }
];

Использование регулярных выражений для маршрутов

Регулярные выражения в Universal Router позволяют строго ограничивать, какие значения могут принимать параметры:

const routes = [
  {
    path: '/order/:orderId(\\d+)',
    action: ({ params }) => getOrderById(params.orderId)
  }
];

Здесь :orderId(\\d+) гарантирует, что параметр состоит только из цифр. Любая попытка передать текст будет отклонена на этапе маршрутизации.


Логирование и аудит параметров

Для повышения безопасности целесообразно вести журнал всех необычных или подозрительных запросов:

const routes = [
  {
    path: '/profile/:id',
    action: ({ params }) => {
      if (!/^\d+$/.test(params.id)) {
        console.warn('Попытка передачи некорректного ID:', params.id);
      }
      return fetchProfile(params.id);
    }
  }
];

Такой подход помогает выявлять атаки на ранней стадии и обеспечивает аудит изменений, связанных с параметрами маршрутов.


Резюме практик защиты

  • Валидация параметров: числовые, текстовые, перечисления.
  • Экранирование данных при выводе в HTML.
  • Использование безопасных методов передачи в URL (encodeURIComponent).
  • Ограничение вложенности маршрутов и проверка на каждом уровне.
  • Регулярные выражения для строгих шаблонов параметров.
  • Логирование подозрительных значений для аудита безопасности.

Эти меры обеспечивают надежную защиту приложений на основе Universal Router от большинства видов инъекций, предотвращая непреднамеренное выполнение кода или обход системы маршрутизации.