40 lines
2.1 KiB
JavaScript
40 lines
2.1 KiB
JavaScript
/**
|
|
* src/middleware/csp.js — Content Security Policy директивы.
|
|
*
|
|
* Экспортирует объект CSP_DIRECTIVES для передачи в helmet({ contentSecurityPolicy }).
|
|
* Так CSP применяется один раз вместе с остальными заголовками helmet.
|
|
*
|
|
* Текущее ограничение: EJS-шаблоны используют inline <style>, <script> и
|
|
* атрибуты onclick/style= — поэтому 'unsafe-inline' пока необходим.
|
|
* Это всё равно лучше отключённого CSP: блокируются внешние ресурсы,
|
|
* фреймирование, object/embed, переопределение base.
|
|
*
|
|
* Что блокирует эта политика:
|
|
* - Загрузку скриптов/стилей с внешних доменов
|
|
* - Фреймирование страниц (clickjacking) — frame-ancestors 'none'
|
|
* - <object>, <embed>, <applet> — object-src 'none'
|
|
* - Переопределение <base href> — base-uri 'self'
|
|
* - POST форм на внешние домены — form-action 'self'
|
|
*
|
|
* TODO (при переносе стилей в .css и скриптов в .js файлы):
|
|
* убрать 'unsafe-inline', добавить nonce или hash для оставшихся inline-блоков.
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
const CSP_DIRECTIVES = {
|
|
defaultSrc: ["'self'"],
|
|
// 'unsafe-inline' нужен пока стили и скрипты inline в EJS.
|
|
scriptSrc: ["'self'", "'unsafe-inline'"],
|
|
styleSrc: ["'self'", "'unsafe-inline'"],
|
|
imgSrc: ["'self'", 'data:'], // data: для SVG-иконок
|
|
fontSrc: ["'self'"],
|
|
connectSrc: ["'self'"],
|
|
objectSrc: ["'none'"], // блок <object>/<embed>/<applet>
|
|
baseUri: ["'self'"], // блок переопределения <base>
|
|
formAction: ["'self'"], // POST только на свой домен
|
|
frameAncestors: ["'none'"], // clickjacking protection
|
|
};
|
|
|
|
module.exports = { CSP_DIRECTIVES };
|