--- name: sfnext-security description: >- Configure Storefront Next security response headers, Content Security Policy (CSP), CSP contributors, Cloudflare Turnstile bot protection, and the shared cookie domain. Use for "Refused to load the script/connect/image" CSP violations, adding a third-party origin, app.security.headers, defaultCspDirectives, csp reportOnly rollout, writing a CSP contributor under src/middlewares/csp-contributors, HSTS or Permissions-Policy, Turnstile widget or enforceTurnstile, TURNSTILE_SECRET_KEYS, log-only rollout, or app.cookies.domain across subdomains. Do not use for auth tokens, cookie names or login flows (use `storefront-next:sfnext-authentication`), SFRA proxy routing (use `storefront-next:sfnext-hybrid-storefronts`), or consent banners and tracking (use `storefront-next:sfnext-analytics-consent`). --- # Storefront Next Security Security is configured under `app.security` in `config.server.ts`: `security.headers` for response headers and CSP, `security.turnstile` for bot protection. Cookie sharing is `app.cookies.domain`. Your project ships deeper docs: `docs/README-SECURITY-HEADERS.md`, `docs/README-TURNSTILE.md`, `docs/README-COOKIE-DOMAIN.md`. Read them for details; this skill is the task guide. ## Default headers Every storefront gets these with no opt-in, from `@salesforce/storefront-next-runtime/security` via the `securityHeadersMiddleware` in `src/middlewares/security-headers.server.ts`: | Header | Default | |---|---| | `Content-Security-Policy` | Strict, nonce-based (no `'unsafe-inline'` scripts, no `'unsafe-eval'`) | | `Strict-Transport-Security` | Sent on Managed Runtime only, suppressed locally | | `X-Frame-Options` | `SAMEORIGIN` | | `X-Content-Type-Options` | `nosniff` | | `Referrer-Policy` | `strict-origin-when-cross-origin` | | `Permissions-Policy` | `camera=(), microphone=(), geolocation=()` | The CSP directive table (which origins `script-src`, `connect-src`, `img-src`, and `frame-src` allow by default) is in `docs/README-SECURITY-HEADERS.md`. The per-request nonce is read in `root.tsx` and must be forwarded to any inline `