kepler.gl работает поверх React и deck.gl, обрабатывая большие объёмы геоданных, пользовательские конфигурации слоёв, стили визуализации и параметры фильтрации, которые часто поступают из внешних источников: URL-параметров, JSON-конфигураций, API ответов и файлов импорта. Именно эта архитектура делает вопрос XSS-защиты не формальным дополнением, а критическим элементом безопасности.
XSS в контексте Kepler.gl возникает не только через классические HTML-инъекции, но и через менее очевидные каналы:
Особенность подобных систем заключается в том, что они часто воспринимаются разработчиками как «чисто визуальные», хотя на практике они могут рендерить данные в DOM, включая SVG и HTML-оверлеи.
Любая строка, пришедшая извне, должна рассматриваться как потенциально опасная. Это относится даже к:
Визуализационные библиотеки нередко автоматически отображают эти значения в интерфейсе, что создаёт риск внедрения скриптов через неэкранированный вывод.
Ключевой принцип: данные не должны интерпретироваться как HTML ни при каких условиях.
Наиболее уязвимые зоны — элементы, где текст отображается динамически:
Если используется конструкция вида:
<div dangerouslySetInnerHTML={{ __html: userValue }} />
то любое значение userValue, пришедшее из датасета,
становится точкой XSS-эксплуатации.
Безопасная альтернатива заключается в использовании текстового рендера:
<div>{userValue}</div>
React автоматически экранирует содержимое, предотвращая интерпретацию HTML.
Если по архитектурным причинам требуется поддержка ограниченного HTML (например, для форматирования описаний), применяется строгая санитизация:
import DOMPurify from 'dompurify';
const safeHtml = DOMPurify.sanitize(userInput, {
USE_PROFILES: { html: true }
});
Важно понимать, что даже санитизация не должна применяться к геоданным по умолчанию. В системах визуализации предпочтительнее полностью отказаться от HTML в данных слоя.
Kepler.gl активно использует сериализацию состояния карты, включая:
При хранении состояния в URL возникает риск инъекций через параметры, которые затем десериализуются и отображаются в интерфейсе.
Проблемная схема:
Безопасный подход включает:
Пример валидации:
function validateMapConfig(config) {
return (
typeof config === 'object' &&
typeof config.visState === 'object' &&
Array.isArray(config.visState.layers)
);
}
Расширяемость Kepler.gl через кастомные компоненты увеличивает поверхность атаки. Особенно опасны:
Каждый кастомный слой должен соблюдать правило: не выполнять интерпретацию строк как кода или HTML.
Пример безопасного render-функционала:
const renderTooltip = (object) => {
return (
<div>
<div>{object.name}</div>
<div>{String(object.value)}</div>
</div>
);
};
Нежелательно использовать:
innerHTMLДаже при корректной реализации на уровне React важно ограничить выполнение скриптов через CSP:
Content-Security-Policy:
default-src 'self';
script-src 'self';
object-src 'none';
base-uri 'self';
Для геовизуальных приложений критично:
CSP снижает ущерб даже при ошибке в обработке данных.
В Kepler.gl визуализация часто использует SVG через deck.gl и overlay-слои. SVG может содержать:
<script> тегиonload, onerror)Если SVG генерируется из пользовательских данных без фильтрации, он становится полноценным XSS-вектором.
Безопасная стратегия:
Даже параметры визуального стиля могут быть использованы для атак в редких сценариях, если они интерполируются в CSS без проверки.
Пример риска:
style={{ backgroundImage: `url(${userInput})` }}
Если userInput содержит jav * ascript: или
data-URI, возможна эксплуатация.
Правильный подход:
https, http)Архитектурно важно разделять:
Смешивание этих слоёв приводит к тому, что пользовательские данные начинают влиять на DOM-структуру.
Правильная модель:
CSV и JSON импорты — частый источник XSS в визуализациях. Опасные сценарии:
<img src=x oner ror=alert(1)>Решение:
const sanitizeRow = (row) =>
Object.fromEntries(
Object.entries(row).map(([k, v]) => [k, String(v)])
);
Наиболее устойчивые реализации Kepler.gl-подобных систем строятся по принципу минимального доверия:
Такой подход превращает XSS из вероятной угрозы в практически исключённый класс уязвимостей даже при работе с внешними источниками данных.