Защита от XSS через URL

XSS (Cross-Site Scripting) — одна из наиболее распространённых угроз в веб-разработке. Она возникает, когда злоумышленник внедряет вредоносный скрипт в веб-приложение через вводимые пользователем данные или параметры URL. В контексте библиотек маршрутизации, таких как Navigo, особое внимание уделяется безопасной обработке URL и параметров маршрутов.

При использовании Navigo маршруты часто принимают динамические параметры. Например:

const router = new Navigo('/');
router.on('/user/:id', (params) => {
  console.log(params.id);
});

Если значение :id подставляется напрямую в DOM без очистки, возникает риск XSS.

Очистка параметров маршрута

Для предотвращения внедрения скриптов необходимо всегда экранировать или фильтровать пользовательский ввод. Один из подходов — использовать безопасные функции для работы с текстом, выводимым на страницу:

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

router.on('/user/:id', (params) => {
  const safeId = escapeHTML(params.id);
  document.getElementById('userId').textContent = safeId;
});

Здесь escapeHTML преобразует потенциально опасные символы в безопасные HTML-сущности, исключая возможность выполнения скриптов.

Ограничение формата параметров

Navigo поддерживает использование регулярных выражений для валидации параметров. Это позволяет ограничивать значения строго ожидаемыми формами:

router.on('/product/:productId(\\d+)', (params) => {
  console.log('Product ID:', params.productId);
});

В этом примере маршрут принимает только числовые идентификаторы. Любые символы, не соответствующие \d+, будут автоматически отвергнуты и не попадут в обработчик.

Проверка query-параметров

Помимо динамических сегментов маршрута, часто используются query-параметры. Их необходимо валидировать отдельно:

router.on('/search', () => {
  const queryParams = new URLSearchParams(window.location.search);
  const searchTerm = queryParams.get('q');
  if (searchTerm) {
    const safeTerm = escapeHTML(searchTerm);
    document.getElementById('results').textContent = safeTerm;
  }
});

Использование URLSearchParams гарантирует корректное разбор query-строки, а дополнительное экранирование защищает от XSS через параметры поиска.

Работа с внутренними ссылками

Даже при использовании Navigo важно контролировать вставку данных в атрибуты HTML. Прямое использование innerHTML с динамическими значениями крайне опасно:

// Опасно
document.getElementById('content').innerHTML = params.id;

// Безопасно
document.getElementById('content').textContent = escapeHTML(params.id);

Для безопасного создания HTML-элементов лучше использовать методы создания элементов через document.createElement и appendChild, избегая конкатенации строк с HTML.

Настройка маршрутов для безопасного поведения

Navigo позволяет задавать fallback-маршруты и обрабатывать несуществующие пути. Это снижает риск XSS через случайные или некорректные URL:

router.notFound(() => {
  document.getElementById('content').textContent = 'Страница не найдена';
});

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

Ограничение внедрения скриптов через hash-маршруты

При использовании hash-маршрутизации важно контролировать символ # в URL. Даже если hash используется для состояния приложения, нельзя напрямую вставлять его в DOM без экранирования:

router.on('/page/:section', (params) => {
  const section = escapeHTML(params.section);
  document.getElementById('sectionTitle').textContent = section;
});

Любые спецсимволы, включая <script>, будут безопасно преобразованы.

Итоговые рекомендации по защите URL

  • Всегда экранировать значения параметров перед вставкой в DOM.
  • Использовать регулярные выражения для валидации динамических сегментов маршрутов.
  • Контролировать query-параметры и использовать URLSearchParams.
  • Избегать innerHTML и других методов, которые могут выполнить скрипт.
  • Настраивать notFound-маршруты для безопасного поведения при неизвестных URL.
  • При hash-маршрутах экранировать данные перед выводом.

Правильное сочетание этих техник обеспечивает защиту от большинства XSS-атак, связанных с URL, в приложениях на базе Navigo.