Security and CSP Policies
1) Why do we need security policies
The modern frontend and API depend on many sources (CDN, analytics, PSP, 3DS, chats). Without tough policies, the risks of XSS, clickjacking, data leaks and session hijacking increase. Security policies limit what is allowed by default by moving the browser to the allow-list model.
2) Basic pillars
CSP (Content Security Policy) is a centralized "menu" of permitted JS/CSS/media sources and behaviors.
Trusted Types - Type-level protection against DOM-XSS.
SRI (Subresource Integrity) - control the integrity of scripts/styles.
COOP/COEP/CORP - rigid isolation of contexts and resources between sources.
Fetch Metadata ('Sec-Fetch-') is a server solution for filtering cross-site requests.
CORS - cross-domain API access policy.
Classic titles: HSTS, 'X-Frame-Options'/'frame-ancestors', 'Referrer-Policy', 'Permissions-Policy', SameSite-cookies.
3) CSP: Basis and Principles
3. 1 Directives (key)
'default-src '- default for other directives.
'script-src '- JS sources, nonce/hash,'strict-dynamic', 'report-sample'.
'style-src '- CSS sources; minimize'unsafe-inline '.
`img-src`, `font-src`, `media-src`, `object-src` (usually `none`).
'connect-src '- network requests (XHR/fetch/WebSocket).
'frame-src'/'child-src'- third-party frames (PSP, 3DS).
'frame-ancestors' - who can embed our site (anti-clickjacking).
'base-uri '- prohibit substitution of' <base> '.
'form-action '- where forms are allowed to be submitted.
'upgrade-insecure-requests', 'block-all-mixed-content' - fighting the HTTP/HTTPS mix.
'report-uri'/'report-to'- where to send violations.
3. 2 Nonce and hash
Nonce approach: generate a crypto-random' nonce' for each HTTP response, add '<script nonce =..."">' to inline scripts and 'script-src' nonce-... "
Hash approach: fixed hash of inline content. Suitable for static HTML, inconvenient for dynamics.
'strict-dynamic ': trust only scripts loaded by a "trusted" script (with nonce/hash). Removes the need to list target domains during dynamic boot, but requires modern browsers.
3. 3 Banning 'unsafe-'
Avoid 'unsafe-inline', 'unsafe-eval'. If the framework requires eval (for example, source-map in dev), include only on dev.
For styles - use 'nonce' or 'hash', if possible without inlines.
3. 4 Example of strict CSP (battle point)
Content-Security-Policy:
default-src 'none';
base-uri 'self';
object-src 'none';
script-src 'self' 'nonce-{RANDOM}' 'strict-dynamic' https://www. googletagmanager. com;
style-src 'self' 'nonce-{RANDOM}';
img-src 'self' data: https://images. example-cdn. com;
font-src 'self' https://fonts. gstatic. com;
connect-src 'self' https://api. example. com wss://ws. example. com;
frame-src https://3ds. psp. com https://pay. psp. com;
frame-ancestors 'none';
form-action 'self' https://pay. psp. com;
upgrade-insecure-requests;
report-to csp-endpoint; report-sample
4) Trusted Types (DOM-XSS)
Enable the directive: 'Content-Security-Policy: require-trusted-types-for 'script'; trusted-types app default`.
Create a single policy in the code ('window. trustedTypes. createPolicy('app', { createHTML() {... } })`).
Prohibit insecure assignments ('element. innerHTML =...`) without Trusted Types.
Framework integration (React/Angular/Vue): use secure rendering APIs, avoid dangerous dangerouslySetInnerHTML.
5) SRI (CDN Integrity)
For external' <script> '/' <link> ', use' integrity =" sha256-... "crossorigin =" anonymous"'.
SRI supplements, not replaces, CSP. When upgrading a CDN version, update the hash.
6) Clickjacking and frames
The modern way is' frame-ancestors' (replaces the outdated 'X-Frame-Options').