Библиотека Globalize построена вокруг данных CLDR (Unicode Common
Locale Data Repository). Эти данные включают правила форматирования
чисел, дат, валют, склонения, множественные формы и прочие региональные
особенности. В отличие от монолитных решений, Globalize сознательно
разделяет код и данные, что делает вопрос безопасной загрузки критически
важным.
Ключевая особенность архитектуры — отсутствие встроенных
локалей. Разработчик сам отвечает за поставку данных. Это
создаёт гибкость, но одновременно открывает поверхность атаки, если
данные подгружаются без контроля.
Основной принцип:
Любые данные локализации следует считать внешними и
потенциально недоверенными, даже если они приходят из собственного
CDN
Источники данных и уровни
доверия
Типичная схема работы включает несколько источников:
1. Статические JSON-файлы CLDR
Обычно поставляются через npm-пакеты или сборку:
cldr-numbers-full
cldr-dates-full
cldr-core
Эти данные считаются высокодоверенными, если:
- загружены на этапе сборки (build-time)
- проходят контроль версий
- хэшируются в процессе сборки
2. Динамическая загрузка
через HTTP/CDN
Используется для:
- уменьшения размера бандла
- поддержки множества локалей
- lazy-loading языков
Этот путь считается среднедоверенным, поскольку:
- возможна подмена CDN
- возможны атаки через компрометированный источник
- возможно вмешательство на уровне прокси
3. Пользовательские или
внешние локали
Наименее доверенный источник:
- плагины
- сторонние сервисы
- runtime-конфигурации от пользователя
Такие данные должны рассматриваться как небезопасные по
умолчанию
Опасности при
загрузке локализационных данных
Подмена числовых и
валютных форматов
Если атакующий изменяет CLDR-данные, возможны:
- неверное отображение валютных символов
- подмена разделителей тысяч/десятичных
- манипуляции с отображением сумм
Это не просто UI-баг, а потенциальная финансовая уязвимость.
Инъекции через строковые
форматы
Хотя Globalize не выполняет код из данных, опасность возникает на
уровне приложения:
- данные могут попадать в DOM
- форматированные строки могут быть вставлены через
innerHTML
- локализованные сообщения могут содержать HTML
Поломка логики парсинга
Изменённые правила могут привести к:
- неверной интерпретации дат
- ошибкам сортировки
- сбоям в валидации ввода пользователя
Принципы безопасной загрузки
1. Иммутабельность
локализационных данных
После загрузки данные должны считаться неизменяемыми:
- заморозка объектов (
Object.freeze)
- отказ от runtime-мутаций
- изоляция модулей локалей
Пример подхода:
- локали собираются в build-step
- результат включается в финальный бандл
- runtime не имеет права их изменять
2. Версионирование CLDR
Любая версия CLDR должна быть зафиксирована:
- запрещены диапазоны зависимостей
- исключены автообновления без проверки
- требуется контроль совместимости с Globalize
Важно учитывать:
- разные версии CLDR могут менять правила форматирования
- несовместимость приводит к логическим ошибкам без явных падений
3. Контроль источников
загрузки
При динамической загрузке:
- разрешён только whitelist доменов
- применяется HTTPS обязательно
- исключается загрузка с произвольных URL
Дополнительно:
- Content Security Policy (CSP)
- Subresource Integrity (SRI) для статических файлов
- защита от DNS spoofing через pinned endpoints
4. Сборка локалей на этапе
build-time
Наиболее безопасная стратегия:
- загрузка CLDR через npm
- генерация локалей в build pipeline
- упаковка в JS/JSON артефакты
Преимущества:
- отсутствие сетевой зависимости в runtime
- предсказуемость поведения
- возможность аудита данных
5. Изоляция слоя
форматирования
Функции Globalize должны быть отделены от UI:
- форматирование чисел и дат не должно напрямую возвращать HTML
- результаты должны быть строками без разметки
- HTML-рендеринг выполняется отдельно
Это снижает риск:
- XSS через локализованные строки
- подмены структуры DOM
Безопасная
загрузка через модульную архитектуру
Типичная безопасная схема:
Импорт ядра Globalize
Загрузка CLDR core данных
Подключение нужных модулей:
Инициализация локали
Фиксация состояния
Критически важно, чтобы порядок инициализации был неизменяемым. Любое
частичное подключение может привести к неконсистентному состоянию
форматирования.
Проверка целостности данных
При загрузке через сеть применяются механизмы:
Hash-based verification
- SHA-256 для JSON-ресурсов
- проверка перед парсингом
- отказ при несовпадении
Schema validation
- проверка структуры CLDR JSON
- валидация типов полей
- контроль обязательных ключей
Runtime sanity checks
Работа с динамическими
локалями
Динамическая загрузка локали требует строгого пайплайна:
- запрос локали
- проверка источника
- загрузка JSON
- валидация структуры
- регистрация в Globalize
- активация локали
Любое отклонение должно приводить к:
- отказу загрузки
- fallback на дефолтную локаль (например,
en)
Fallback-стратегии
Безопасная система всегда включает резервные сценарии:
- отсутствие локали → переход на базовую
- повреждённые CLDR данные → игнорирование пакета
- частичная загрузка → откат к предыдущей версии
Fallback не должен зависеть от сети.
Опасные анти-паттерны
Использование
eval-подобных механизмов
Даже косвенное выполнение строк из локализационных данных
недопустимо.
Прямая вставка
форматированных строк в HTML
Пример опасной практики:
element.innerHTML = Globalize.formatMessage(data)
Правильный подход:
textContent вместо innerHTML
Загрузка локалей без
фиксации версии
Любой “latest” endpoint создаёт риск непредсказуемого поведения.
Доверие пользовательским
локалям
Если система позволяет пользователю загружать собственные правила
форматирования, это должно:
- выполняться в sandbox
- не влиять на глобальное состояние
- не пересекаться с системными локалями
Контроль в браузерной среде
В браузере безопасность усиливается дополнительными механизмами:
- CSP ограничивает загрузку скриптов и JSON
- module script integrity предотвращает подмену модулей
- CORS исключает доступ к произвольным источникам
Важно учитывать, что JSON-локали могут быть таким же вектором атаки,
как и JavaScript.
Контроль в Node.js среде
В серверной среде отсутствуют браузерные ограничения, поэтому
усиливаются:
- контроль файловой системы
- фиксация npm-версий
- использование lock-файлов (
package-lock.json,
pnpm-lock.yaml)
- аудит зависимостей
Дополнительно:
- запрет динамической загрузки локалей с внешних URL без
прокси-валидации
Поведение при
частично повреждённых данных
Globalize может продолжать работу при неполных данных, но это должно
быть управляемым:
- отключение конкретного типа форматирования
- логирование отсутствующих CLDR сегментов
- переход на минимальный набор функций
Недопустимо:
- молчаливое использование некорректных значений
- автоматическое “догадывание” правил
Модель доверенной границы
данных
Архитектурно данные локализации должны проходить три границы:
Transport layer
- HTTPS
- SRI
- проверка источника
Validation layer
- schema check
- hash check
- version check
Application layer
- иммутабельность
- изоляция
- безопасное использование в форматировании
Только после прохождения всех уровней данные считаются пригодными для
использования в Globalize.