Content Security Policy (CSP) представляет собой механизм защиты веб-приложений, ограничивающий источники загрузки и выполнения ресурсов. При интеграции с i18next в клиентских приложениях CSP становится критическим фактором архитектуры, поскольку система интернационализации опирается на динамическую загрузку переводов, выполнение шаблонов и работу с асинхронными загрузчиками ресурсов.
CSP управляет следующими аспектами, непосредственно затрагивающими работу i18next:
script-src)unsafe-eval)connect-src)i18next в браузере обычно опирается на загрузчики ресурсов (backend
plugins), которые используют fetch или
XMLHttpRequest. При строгих CSP-политиках это требует
явного разрешения соответствующих источников.
Одним из наиболее чувствительных аспектов CSP является запрет inline-скриптов. Многие приложения интернационализации исторически используют встроенную инициализацию:
<script>
i18next.init({
lng: 'en',
resources: {
en: {
translation: {
key: 'value'
}
}
}
});
</script>
При политике CSP без unsafe-inline такой код
блокируется. Альтернативный подход предполагает вынесение инициализации
в отдельный файл:
import i18next from 'i18next';
i18next.init({
lng: 'en',
fallbackLng: 'en',
backend: {
loadPath: '/locales/{{lng}}/{{ns}}.json'
}
});
И подключение через разрешённый источник:
<script src="/assets/app.js"></script>
Некоторые конфигурации i18next или связанных плагинов могут косвенно
затрагивать eval-подобное поведение. CSP-параметр
unsafe-eval блокирует динамическое выполнение строкового
кода.
На практике современные версии i18next не используют
eval, однако риск возникает при:
Рекомендуемая конфигурация CSP исключает unsafe-eval,
при этом проверяется совместимость всех зависимостей.
Основной сценарий работы i18next в production — загрузка переводов через backend:
import Backend from 'i18next-http-backend';
import i18next from 'i18next';
i18next
.use(Backend)
.init({
lng: 'en',
backend: {
loadPath: '/locales/{{lng}}/{{ns}}.json'
}
});
CSP должна явно разрешать домен загрузки:
Content-Security-Policy:
default-src 'self';
script-src 'self';
connect-src 'self';
img-src 'self';
style-src 'self';
При загрузке переводов с CDN:
connect-src 'self' https://cdn.example.com;
Любое несоответствие приводит к блокировке XHR/fetch запросов, что делает систему локализации неработоспособной.
i18next использует JSON как основной формат хранения переводов. CSP
не ограничивает JSON напрямую, однако ограничения накладываются через
connect-src и default-src.
При архитектуре с разделением namespaces:
i18next.init({
ns: ['common', 'auth', 'dashboard'],
defaultNS: 'common'
});
запросы к ресурсам приобретают форму:
/locales/en/common.json
/locales/en/auth.json
Каждый endpoint должен быть разрешён политикой CSP.
При использовании CDN для переводов или статических ресурсов возникает необходимость расширения CSP:
connect-src 'self' https://i18n.cdn.example.com;
и при необходимости:
img-src 'self' https://images.cdn.example.com;
Если перевод включает HTML-строки или rich-text содержимое,
усиливается риск XSS, и CSP должна быть дополнена
trusted-types (в современных браузерах):
require-trusted-types-for 'script';
Механизм интерполяции i18next:
i18next.t('welcome', { name: userName });
сам по себе безопасен, однако риск возникает при:
dangerouslySetInnerHTML (React)CSP не предотвращает логические XSS напрямую, но усиливает защитный контур при запрете inline HTML и скриптов.
Некоторые конфигурации используют:
i18next.t('html_key', { interpolation: { escapeValue: false } });
При отключении экранирования возможна вставка HTML, что в сочетании с
ослабленной CSP (unsafe-inline) увеличивает поверхность
атаки.
Рекомендуемая практика:
escapeValue: trueunsafe-inlineВ архитектурах PWA переводы часто кэшируются через Service Worker:
self.addEventListener('fetch', event => {
if (event.request.url.includes('/locales/')) {
event.respondWith(caches.match(event.request));
}
});
CSP должна учитывать:
worker-src 'self';
и корректную настройку connect-src, если Service Worker
делает сетевые запросы к источникам переводов.
При строгой CSP с nonce:
Content-Security-Policy: script-src 'self' 'nonce-random123'
инициализация i18next должна выполняться исключительно в внешних модулях, загруженных через разрешённые скрипты:
// app.js
import i18next from 'i18next';
export function initI18n() {
return i18next.init({
lng: 'en'
});
}
Inline-конфигурации исключаются полностью.
Базовая безопасная конфигурация:
Content-Security-Policy:
default-src 'self';
script-src 'self';
connect-src 'self';
img-src 'self';
style-src 'self';
Расширенная конфигурация с CDN:
Content-Security-Policy:
default-src 'self';
script-src 'self' https://cdn.example.com;
connect-src 'self' https://i18n.cdn.example.com;
img-src 'self' https://assets.cdn.example.com;
style-src 'self';
При нарушении CSP поведение обычно проявляется следующим образом:
отсутствует загрузка переводов
t() возвращает ключи вместо значений
XHR запросы к /locales/* блокируются
ошибки в консоли вида:
Диагностика сводится к анализу:
connect-srcdefault-srcНаиболее устойчивые подходы включают:
При соблюдении этих ограничений i18next функционирует в строгих CSP-окружениях без деградации функциональности локализации.