Content Security Policy

Content Security Policy (CSP) — механизм безопасности браузера, ограничивающий источники загрузки ресурсов и выполнение кода на странице. В проектах с использованием Headroom.js CSP играет важную роль, поскольку библиотека взаимодействует с DOM, добавляет/удаляет CSS-классы и может использовать встроенные стили или скрипты в зависимости от архитектуры приложения.

Headroom.js сам по себе не внедряет небезопасный код, однако неправильная настройка CSP может привести к блокировке его работы или сопутствующих элементов интерфейса.


Основные принципы CSP

CSP задаётся через HTTP-заголовок:

Content-Security-Policy: <директивы>

или через <meta>-тег:

<meta http-equiv="Content-Security-Policy" content="default-src 'self'">

Ключевые директивы:

  • default-src — базовое правило для всех типов ресурсов
  • script-src — источники JavaScript
  • style-src — источники CSS
  • img-src — источники изображений
  • connect-src — AJAX, WebSocket и API-запросы
  • font-src — шрифты
  • frame-src — iframe

Подключение Headroom.js с учётом CSP

Headroom.js обычно подключается через:

<script src="headroom.min.js"></script>

или через CDN:

<script src="https://cdn.jsdelivr.net/npm/headroom.js@0.12.0/dist/headroom.min.js"></script>

Настройка CSP для скриптов

Чтобы разрешить загрузку Headroom.js:

script-src 'self' https://cdn.jsdelivr.net

Если используется локальная версия:

script-src 'self'

Inline-скрипты и CSP

Headroom.js часто инициализируется через встроенный скрипт:

<script>
var header = document.querySelector("header");
var headroom = new Headroom(header);
headroom.init();
</script>

По умолчанию CSP блокирует inline-скрипты. Для их разрешения есть несколько вариантов:

1. Использование 'unsafe-inline' (не рекомендуется)

script-src 'self' 'unsafe-inline'

Недостаток — снижение безопасности.


2. Использование nonce

Более безопасный способ:

HTML:

<script nonce="abc123">
var header = document.querySelector("header");
var headroom = new Headroom(header);
headroom.init();
</script>

CSP:

script-src 'self' 'nonce-abc123'

Nonce должен генерироваться динамически на сервере.


3. Вынесение кода в отдельный файл

Рекомендуемый подход:

<script src="app.js"></script>
script-src 'self'

Работа с CSS и анимациями Headroom.js

Headroom.js управляет классами:

  • headroom
  • headroom--pinned
  • headroom--unpinned
  • headroom--top
  • headroom--not-top

Пример CSS:

.headroom {
  transition: transform 0.3s ease-in-out;
}

.headroom--unpinned {
  transform: translateY(-100%);
}

.headroom--pinned {
  transform: translateY(0);
}

CSP для стилей

Если стили находятся в отдельном файле:

style-src 'self'

Если используются inline-стили:

<style>
...
</style>

необходимо:

style-src 'self' 'unsafe-inline'

или:

style-src 'self' 'nonce-xyz'

CSP и динамическое изменение классов

Headroom.js изменяет DOM, добавляя и удаляя классы. Это не нарушает CSP, поскольку:

  • CSP не запрещает манипуляции DOM
  • ограничения касаются только загрузки ресурсов и выполнения кода

Таким образом, базовая работа библиотеки не требует дополнительных разрешений.


CSP и сторонние зависимости

Headroom.js может использоваться вместе с:

  • CSS-фреймворками (например, Bootstrap)
  • системами сборки (Webpack, Vite)
  • SPA-фреймворками (React, Vue)

Возможные проблемы

  1. CDN-ресурсы заблокированы
  2. Inline-скрипты запрещены
  3. Динамически создаваемые стили блокируются

Пример строгой CSP для проекта с Headroom.js

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

Если используется CDN:

script-src 'self' https://cdn.jsdelivr.net;
style-src 'self' https://cdn.jsdelivr.net;

Использование hash для inline-кода

Альтернатива nonce — использование hash:

  1. Берётся содержимое скрипта
  2. Вычисляется SHA-256
script-src 'self' 'sha256-<hash>'

Преимущество — статичность Недостаток — сложность поддержки при изменении кода


CSP и сборщики (Webpack/Vite)

При использовании сборщиков:

  • код Headroom.js включается в бандл
  • CSP упрощается
script-src 'self'

Важно:

  • отключать inline eval (если используется dev-сборка)
  • избегать eval() и new Function()

CSP и режим отчётности

Для отладки используется:

Content-Security-Policy-Report-Only

Пример:

Content-Security-Policy-Report-Only:
  default-src 'self';
  report-uri /csp-report

Браузер не блокирует ресурсы, а только сообщает о нарушениях.


Типичные ошибки при использовании CSP с Headroom.js

1. Блокировка CDN

Ошибка:

Refused to load script from ...

Решение:

script-src 'self' https://cdn.jsdelivr.net

2. Inline-скрипт не выполняется

Ошибка:

Refused to execute inline script

Решение:

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

3. CSS-анимации не работают

Причина:

  • стили заблокированы CSP

Решение:

style-src 'self'

или добавить CDN


4. Использование eval в сторонних библиотеках

Некоторые сборки могут использовать:

eval()

CSP блокирует это:

script-src 'self'

Чтобы разрешить:

script-src 'self' 'unsafe-eval'

Но это снижает безопасность.


Безопасная конфигурация для production

Рекомендуемые принципы:

  • отказ от inline-скриптов
  • использование локальных ресурсов
  • минимизация внешних источников
  • использование nonce вместо unsafe-inline
  • строгие директивы default-src

Пример:

Content-Security-Policy:
  default-src 'self';
  script-src 'self';
  style-src 'self';
  img-src 'self' dat a:;
  font-src 'self';
  connect-src 'self';
  object-src 'none';
  base-uri 'self';
  frame-ancestors 'none';

Взаимодействие CSP и UX при использовании Headroom.js

Headroom.js управляет видимостью шапки страницы при прокрутке. При неправильной CSP:

  • скрипт не запускается
  • классы не применяются
  • анимации отсутствуют

Это приводит к:

  • “залипшей” шапке
  • отсутствию скрытия/появления
  • нарушению визуальной логики интерфейса

Проверка и тестирование CSP

Инструменты:

  • DevTools (Console, Network)
  • заголовки HTTP
  • отчёты CSP

Проверка включает:

  • загрузку страницы
  • прокрутку (инициация Headroom)
  • анализ ошибок безопасности

Рекомендации по интеграции

  • подключать Headroom.js через сборщик
  • избегать inline-кода
  • централизовать стили
  • тестировать CSP в режиме Report-Only
  • постепенно ужесточать политику

Совместимость браузеров

CSP поддерживается:

  • Chrome
  • Firefox
  • Edge
  • Safari (с ограничениями)

Headroom.js не требует специальных разрешений CSP, кроме стандартных правил загрузки скриптов и стилей.


Практический пример

HTML:

<link rel="stylesheet" href="styles.css">
<script src="bundle.js"></script>

CSP:

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

JavaScript (bundle.js):

import Headroom from "headroom.js";

const header = document.querySelector("header");
const headroom = new Headroom(header);

headroom.init();

Такой подход полностью совместим со строгой политикой безопасности.