XSS и инъекции

Любой datepicker, интегрируемый в DOM, становится частью цепочки обработки пользовательского ввода и рендеринга интерфейса. В случае Flatpickr ключевой риск связан не столько с самим вводом даты, сколько с тем, как библиотека взаимодействует с DOM, форматированием строк и пользовательскими callback-функциями.

Основная поверхность атаки формируется из нескольких источников:

  • пользовательские значения в input-полях;
  • кастомные функции форматирования и парсинга;
  • локализации (locale);
  • опции, влияющие на HTML-структуру (altInput, appendTo);
  • хуки жизненного цикла (onChange, onDayCreate, onReady и др.);
  • сторонние плагины и расширения.

Flatpickr не интерпретирует ввод как HTML, однако уязвимости возникают на уровне приложения, когда разработчик начинает подставлять данные библиотеки в DOM без экранирования или смешивает строки с HTML-разметкой.


Вектор внедрения через альтернативные поля ввода

Опция altInput создаёт дополнительное поле, отображающее отформатированную дату. Сам Flatpickr управляет значением через текстовые узлы, однако риск появляется при кастомной синхронизации значений:

flatpickr("#date", {
  altInput: true,
  altFormat: "F j, Y",
  dateFormat: "Y-m-d"
});

Опасность возникает не здесь, а при попытке разработчика вручную модифицировать altInput.value или вставлять туда данные из внешних источников:

// небезопасный паттерн
altInput.value = userProvidedString;

Если далее значение отображается через innerHTML, возникает классическая XSS-ситуация. Flatpickr не экранирует такие вставки, так как не управляет ими.


Форматирование дат и пользовательские функции

Наиболее критичный механизм — formatDate и пользовательские форматтеры. Flatpickr позволяет переопределять отображение даты:

flatpickr("#date", {
  formatDate: (date, format, locale) => {
    return someExternalFormatter(date);
  }
});

Если возвращаемое значение формируется на основе пользовательского ввода или данных сервера без экранирования, оно может содержать HTML/JS-код.

Особенно опасны конструкции:

  • конкатенация строк с HTML;
  • вставка значений из API без фильтрации;
  • использование шаблонных строк с innerHTML на стороне приложения.

Flatpickr здесь выступает лишь транспортом данных, но не фильтром.


Локализация как скрытый источник инъекций

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

flatpickr.localize({
  weekdays: {
    shorthand: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"],
    longhand: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
  }
});

Если такие значения подставляются без контроля, возникает риск внедрения HTML:

longhand: ["Sunday <img src=x oner ror=alert(1)>", ...]

Flatpickr не обязан интерпретировать эти строки как безопасные — они могут попасть в DOM через пользовательские рендеры или кастомные плагины.


Хуки жизненного цикла и выполнение произвольного кода

Flatpickr предоставляет богатый набор callback-функций:

  • onChange
  • onOpen
  • onClose
  • onDayCreate
  • onReady

Наиболее опасный сценарий возникает при использовании данных этих хуков для генерации DOM:

flatpickr("#date", {
  onDayCreate: (dObj, dStr, fp, dayElem) => {
    dayElem.innerHTML = dStr;
  }
});

Если dStr содержит неконтролируемые данные, это прямой XSS-вектор.

Безопасная модель предполагает использование:

  • textContent вместо innerHTML;
  • явного форматирования чисел и дат;
  • отказа от вставки HTML из внешних источников.

Манипуляции через DOM-узлы и appendTo

Опция appendTo позволяет изменить контейнер, в который монтируется календарь. При неправильной реализации она может привести к смешиванию доверенного и недоверенного DOM-контекста:

flatpickr("#date", {
  appendTo: document.querySelector("#user-content")
});

Если #user-content содержит данные, контролируемые пользователем, и внутри него есть обработчики событий или HTML-инъекции, календарь становится частью потенциально скомпрометированного DOM-дерева.

Flatpickr не создаёт изоляции sandbox, поэтому ответственность за контекст лежит полностью на приложении.


Инъекции через пользовательские плагины

Плагины Flatpickr часто расширяют функциональность: добавляют кнопки, кастомные панели, быстрый выбор диапазонов.

Типичный риск:

const plugin = (fp) => {
  return {
    onReady() {
      fp.calendarContainer.innerHTML += userData;
    }
  };
};

Если userData поступает извне, это прямая точка XSS.

Плагины часто становятся слабым звеном, поскольку:

  • пишутся без строгой модели безопасности;
  • используют прямой DOM-injection;
  • предполагают доверенные данные.

Небезопасные паттерны интеграции

Основные ошибки возникают не в самой библиотеке, а в связке Flatpickr + приложение:

1. Использование innerHTML для отображения даты

element.innerHTML = fp.input.value;

2. Подстановка данных API без фильтрации

formatDate: () => apiResponse.label;

3. Использование строк как HTML-контента

dayElem.innerHTML = "<b>" + date + "</b>";

4. Смешивание UI и данных Когда дата одновременно используется как значение и как HTML-контент.


Защита от XSS-инъекций в связке с Flatpickr

Безопасная модель строится вокруг принципа: Flatpickr работает только с данными, DOM формируется отдельно и строго контролируемо.

Ключевые меры:

Использование textContent вместо innerHTML

dayElem.textContent = formattedDate;

Экранирование всех внешних данных Даже если значение кажется “безопасной датой”, оно должно обрабатываться как недоверенный ввод.

Разделение слоёв

  • Flatpickr: логика выбора даты
  • приложение: рендеринг
  • API: данные без HTML

Контроль локалей Локализации должны быть либо статическими, либо проходить через sanitization слой.

Запрет динамического HTML в хуках Любой callback Flatpickr должен рассматриваться как потенциальная точка выполнения кода.


CSP как дополнительный барьер

Content Security Policy снижает последствия XSS, но не устраняет первопричину.

Рекомендуемые ограничения:

  • запрет inline script ('unsafe-inline');
  • ограничение script-src на доверенные домены;
  • запрет unsafe-eval, если не требуется;
  • использование nonce-based политики.

Однако даже строгий CSP не предотвращает DOM-based XSS, если приложение использует innerHTML с недоверенными данными.


Итоговая модель угроз

Flatpickr следует рассматривать как UI-компонент, а не как слой безопасности. Основные угрозы возникают при:

  • передаче внешних данных в форматтеры;
  • использовании HTML в DOM-операциях;
  • неконтролируемых локалях;
  • расширении через плагины;
  • смешении логики данных и представления.

Безопасная архитектура строится на строгом разделении данных и DOM-рендеринга, где любые строки, приходящие из вне, рассматриваются как потенциально исполняемые только на уровне интерпретации браузера, но не как HTML-код.