Content Security Policy

Content Security Policy (CSP) представляет собой механизм браузерной защиты, ограничивающий источники загрузки ресурсов и выполнение скриптов. При использовании картографических библиотек, таких как Leaflet, CSP становится критическим элементом конфигурации, поскольку визуализация карт опирается на внешние тайлы, изображения, стили и динамически создаваемые элементы DOM.

Архитектура Leaflet предполагает активное использование внешних ресурсов: тайл-серверов, маркеров, всплывающих окон, SVG/Canvas слоёв. Любое ограничение политики безопасности напрямую влияет на корректность отображения карты.


Базовая модель CSP и влияние на картографические приложения

CSP управляет следующими категориями ресурсов:

  • script-src — источники JavaScript
  • style-src — стили CSS
  • img-src — изображения и тайлы карт
  • connect-src — AJAX, WebSocket, fetch-запросы
  • worker-src — Web Workers
  • font-src — веб-шрифты

Карты в Leaflet чаще всего страдают от ограничений img-src и connect-src, поскольку тайлы загружаются с внешних серверов.

Пример строгой политики:

Content-Security-Policy:
  default-src 'self';
  script-src 'self';
  style-src 'self';
  img-src 'self';
  connect-src 'self';

При такой конфигурации любая попытка загрузить тайлы с OpenStreetMap или другого провайдера блокируется.


Загрузка тайлов и директива img-src

Основной механизм отображения карты в Leaflet основан на тайловой модели:

L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
  attribution: '© OpenStreetMap contributors'
}).addTo(map);

При CSP требуется разрешить домен тайлового сервера:

Content-Security-Policy:
  img-src 'self' https://tile.openstreetmap.org https://*.tile.openstreetmap.org;

Без этого браузер блокирует загрузку изображений, и карта отображается пустым серым полотном.


connect-src и динамические запросы

Некоторые плагины и расширения Leaflet используют fetch или XHR:

  • геокодирование
  • загрузка GeoJSON
  • получение данных слоёв
  • обращение к REST API

Пример конфигурации:

Content-Security-Policy:
  connect-src 'self' https://api.example.com https://nominatim.openstreetmap.org;

При отсутствии разрешения запросы блокируются на уровне браузера до выполнения JavaScript.


Инлайн-скрипты и проблемы инициализации карты

Инициализация карты часто выполняется через inline <script>:

<script>
  const map = L.map('map').setView([51.505, -0.09], 13);
</script>

При строгой CSP директива script-src запрещает inline-код. Возникает необходимость использования:

  • nonce
  • hash
  • вынесенных файлов

nonce-подход

Content-Security-Policy:
  script-src 'self' 'nonce-r4nd0m';
<script nonce="r4nd0m">
  const map = L.map('map').setView([51.505, -0.09], 13);
</script>

hash-подход

Content-Security-Policy:
  script-src 'self' 'sha256-abc123...';

Внешние стили Leaflet и style-src

Библиотека Leaflet требует подключения собственного CSS:

<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css">

CSP должна разрешать источник:

Content-Security-Policy:
  style-src 'self' https://unpkg.com;

При блокировке CSS нарушается корректное отображение интерфейса карты: маркеры, popups и контролы теряют стилизацию.


Web Workers и расширенные плагины

Некоторые плагины используют Web Workers для:

  • кластеризации маркеров
  • обработки GeoJSON
  • вычисления тепловых карт

CSP требует явного разрешения:

Content-Security-Policy:
  worker-src 'self' blob:;

Отсутствие blob: приводит к сбоям при создании worker-скриптов внутри браузера.


SVG, Canvas и ограничения безопасности

Leaflet поддерживает:

  • SVG-слои
  • Canvas-рендеринг
  • DOM-маркеры

SVG не требует специальных CSP-директив, однако Canvas может быть ограничен при работе с внешними изображениями.

При загрузке тайлов в Canvas возникает проблема tainted canvas, если источник изображения не разрешён CSP.


GeoJSON и безопасность API

При загрузке GeoJSON через HTTP:

fetch('/data/points.geojson')
  .then(r => r.json())
  .then(data => L.geoJSON(data).addTo(map));

CSP должна включать:

Content-Security-Policy:
  connect-src 'self';

Если данные приходят с CDN или API, источник должен быть добавлен в whitelist.


Типовые ошибки при работе CSP с Leaflet

Блокировка тайлов

Причина:

  • отсутствует домен в img-src

Симптом:

  • серый фон карты
  • ошибки в консоли браузера

Блокировка CSS

Причина:

  • отсутствует CDN в style-src

Симптом:

  • отсутствие UI элементов управления картой

Блокировка API запросов

Причина:

  • неверный connect-src

Симптом:

  • пустые слои GeoJSON
  • отсутствие данных маркеров

Блокировка inline-кода

Причина:

  • отсутствие nonce/hash в script-src

Симптом:

  • карта не инициализируется

Безопасная конфигурация для картографических приложений

Практическая CSP-конфигурация для приложений с Leaflet:

Content-Security-Policy:
  default-src 'self';
  script-src 'self' 'nonce-r4nd0m' https://unpkg.com;
  style-src 'self' https://unpkg.com;
  img-src 'self' https://*.tile.openstreetmap.org https://tile.openstreetmap.org data:;
  connect-src 'self' https://nominatim.openstreetmap.org https://api.example.com;
  worker-src 'self' blob:;

Особенности работы с tile providers

Различные поставщики тайлов требуют индивидуальной настройки CSP:

  • OpenStreetMap — tile.openstreetmap.org
  • Mapbox — api.mapbox.com
  • сторонние CDN — произвольные домены

Каждый источник изображений должен быть явно разрешён в img-src.


Data URI и встроенные ресурсы

Некоторые конфигурации Leaflet используют:

  • иконки маркеров через data:
  • SVG строки в popup
  • кастомные canvas-изображения

Для этого требуется:

img-src data:;

Без этого кастомные маркеры не отображаются.


CSP и производительность карт

Жёсткие CSP-политики влияют на архитектуру загрузки:

  • увеличивается количество доменов в whitelist
  • возрастает сложность кэширования
  • усиливается контроль над CDN

В высоконагруженных картографических системах часто выделяются отдельные домены под тайлы, API и статику, чтобы упростить CSP-правила и избежать конфликтов между ресурсами.