Безопасные практики

Navigo — это легковесная библиотека для клиентского маршрутизирования в приложениях на JavaScript. При работе с маршрутизатором важно учитывать безопасность, чтобы предотвратить уязвимости, связанные с неконтролируемым доступом к страницам, передачей параметров и обработкой пользовательского ввода.


Проверка и валидация маршрутов

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

Пример:

const router = new Navigo('/');

router.on('/user/:id', ({ data }) => {
  const userId = parseInt(data.id, 10);
  if (isNaN(userId) || userId <= 0) {
    console.error('Недопустимый ID пользователя');
    return;
  }
  loadUserProfile(userId);
});

Ключевые моменты:

  • Использовать строгую конвертацию типов (parseInt, parseFloat) для числовых параметров.
  • Проверять допустимые диапазоны значений.
  • Не доверять URL-параметрам без проверки — это предотвращает атаки через инъекцию данных.

Ограничение доступа к маршрутам

Для защиты приватных разделов приложения важно внедрять механизмы контроля доступа:

function authGuard(callback) {
  return function(params) {
    if (!userIsLoggedIn()) {
      router.navigate('/login');
      return;
    }
    callback(params);
  };
}

router.on('/dashboard', authGuard(() => {
  renderDashboard();
}));

Рекомендации:

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

Защита от XSS при отображении параметров

Данные из URL могут содержать вредоносный код. Любое использование этих данных в DOM должно быть безопасным:

const safeText = (text) => text.replace(/</g, '&lt;').replace(/>/g, '&gt;');

router.on('/search/:query', ({ data }) => {
  const query = safeText(data.query);
  document.getElementById('results').textContent = `Результаты для: ${query}`;
});

Советы по безопасности:

  • Никогда не вставлять необработанные строки в innerHTML.
  • Для динамического HTML использовать безопасные шаблонизаторы или методы очистки.
  • Любая пользовательская строка должна проходить фильтрацию специальных символов.

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

Navigo поддерживает wildcard-маршруты (*). Использование слишком общих паттернов может привести к случайному раскрытию маршрутов:

router.on('/admin/*', ({ url }) => {
  if (!userIsAdmin()) {
    router.navigate('/forbidden');
    return;
  }
  renderAdminPage(url);
});

Рекомендации:

  • Использовать wildcard только при необходимости.
  • Всегда проверять права пользователя перед загрузкой страниц с wildcard.
  • Минимизировать количество открытых маршрутов с глобальными шаблонами.

Работа с query-параметрами

Query-параметры не обрабатываются автоматически Navigo, поэтому их нужно парсить и фильтровать самостоятельно:

function getQueryParams() {
  const params = {};
  window.location.search.replace(/\??(?:([^=]+)=([^&]*)&?)/g, (_, key, value) => {
    params[key] = decodeURIComponent(value);
  });
  return params;
}

router.on('/products', () => {
  const params = getQueryParams();
  const page = parseInt(params.page, 10) || 1;
  loadProductsPage(page);
});

Практика безопасности:

  • Парсить параметры строго и приводить к нужному типу.
  • Применять фильтры для строковых параметров, если они используются в DOM или запросах.
  • Не доверять параметрам для прямого доступа к данным без проверки прав.

Обработка ошибок маршрутов

Неправильные маршруты или исключения в обработчиках должны корректно обрабатываться, чтобы приложение не раскрывалось злоумышленникам:

router.notFound(() => {
  render404Page();
});

router.on('/profile/:id', ({ data }) => {
  try {
    loadProfile(data.id);
  } catch (e) {
    console.error(e);
    renderErrorPage();
  }
});

Рекомендации:

  • Использовать try/catch в обработчиках маршрутов.
  • Логировать ошибки на стороне сервера или консоли без раскрытия внутренних деталей.
  • Предоставлять безопасные страницы ошибок для пользователей.

Минимизация утечек состояния

Navigo позволяет хранить состояние через router.navigate() с объектом state. Необходимо избегать передачи конфиденциальной информации:

router.navigate('/checkout', { state: { total: 500 } }); // безопаснее передавать ID корзины, а не суммы

Лучшие практики:

  • Хранить в состоянии только идентификаторы, не чувствительные данные.
  • Не использовать URL для передачи паролей, токенов или финансовых данных.
  • Применять серверные проверки для всего состояния, приходящего от клиента.

Поддержка HTTPS и безопасных заголовков

Маршрутизация не защищает данные самостоятельно. Важно комбинировать Navigo с общими мерами безопасности:

  • Использовать HTTPS для всего трафика.
  • Настраивать Content Security Policy (CSP) для предотвращения XSS.
  • Ограничивать доступ к куки и localStorage с флагами HttpOnly и Secure.

Эти методы обеспечивают безопасную работу Navigo в клиентских приложениях и минимизируют риски, связанные с неконтролируемыми URL-параметрами, пользовательскими данными и правами доступа.