Make experience CSP directives configurable (strict CSP for self-hosted OSS)
Author: jonathan-m-borgesCreated Sep 16, 2026Updated Sep 16, 2026
What problem did you meet?
The experience CSP is hardcoded in packages/core/src/middleware/koa-security-headers.ts. Security scanners (OWASP ZAP) and external pentests consistently flag the resulting policy on self-hosted deployments:
- CSP: Wildcard Directive — https: allowed in style-src, img-src, frame-src, font-src
- script-src 'unsafe-inline' / 'unsafe-hashes'
- style-src 'unsafe-inline'
These are rated Medium/High by scanners and must be formally risk-accepted in compliance programs (ISO 27001, SOC 2, client TPRM questionnaires), since there is no configuration path: customUiCsp only appends sources, and no env var / DB config can restrict or override directives. The frame-src: https: case is even marked WARNING (high risk) in the source itself.
Describe what you'd like Logto to have
A supported way for self-hosted operators to tighten the experience CSP, e.g.:
- Allow customUiCsp (or a new sign-in experience / env setting) to replace directives instead of only appending; or
- A "strict CSP" opt-in flag that swaps wildcard sources for an operator-provided allowlist (branding assets, connector origins), and
- Longer term: nonce/hash-based script-src/style-src in the experience app so unsafe-inline/unsafe-hashes can be dropped.
Describe alternatives you've considered
- Header rewrite at the edge (Application Gateway/CDN): works for wildcards but cannot remove unsafe-inline/unsafe-hashes (the experience genuinely uses inline scripts/styles — removing them breaks sign-in), and drifts on every upgrade.
- Forking/patching the image: unsustainable maintenance burden.
- Formal risk acceptance: what we do today, but configurability at the source is the right fix.
Source: logto-io/logto