diff --git a/.env.example b/.env.example index 3c1f741ebd..24faf3d396 100644 --- a/.env.example +++ b/.env.example @@ -117,8 +117,18 @@ TRUST_PROXY=1 # The default policy accommodates what LibreChat actually loads at runtime: # script-src 'wasm-unsafe-eval' HEIC image conversion compiles WebAssembly # worker-src data: Monaco's loader bootstraps workers from data: -# Both are narrower than 'unsafe-eval'. Drop them via CSP_ADDITIONAL_DIRECTIVES -# only if your deployment uses neither the artifact code editor nor HEIC uploads. +# Both are narrower than 'unsafe-eval'. Set these to false to drop them if your +# deployment uses neither HEIC uploads nor the artifact code editor. (The CSP_*_EXTRA +# and CSP_ADDITIONAL_DIRECTIVES variables only add sources; they cannot remove one.) +# CSP_ALLOW_WASM=true +# CSP_ALLOW_DATA_WORKERS=true + +# While CSP is enabled the SPA shell is always sent as `no-store` and the +# INDEX_CACHE_CONTROL / INDEX_PRAGMA / INDEX_EXPIRES overrides are ignored for it. +# A cached shell would pin a single nonce across page loads and users, which is +# precisely what a nonce policy exists to prevent. +# +# SECURITY_HEADERS=false disables CSP too; it is the global kill switch. # Add deployment-specific sources on top of LibreChat's defaults; they are # appended, never replacing them. Comma- or space-separated. Quote values diff --git a/api/server/csp.spec.js b/api/server/csp.spec.js index 2bf550be25..e4d6f07a66 100644 --- a/api/server/csp.spec.js +++ b/api/server/csp.spec.js @@ -92,6 +92,8 @@ describe('Content Security Policy', () => { process.env.CSP_ENABLED = 'true'; process.env.CSP_REPORT_ONLY = 'false'; process.env.CSP_CONNECT_SRC_EXTRA = 'https://telemetry.example.com'; + /* A cacheable override that CSP must refuse for the shell. */ + process.env.INDEX_CACHE_CONTROL = 'public, max-age=3600'; app = require('~/server'); await healthCheckPoll(app); @@ -102,6 +104,7 @@ describe('Content Security Policy', () => { delete process.env.CSP_ENABLED; delete process.env.CSP_REPORT_ONLY; delete process.env.CSP_CONNECT_SRC_EXTRA; + delete process.env.INDEX_CACHE_CONTROL; await mongoServer.stop(); await mongoose.disconnect(); }); @@ -153,6 +156,14 @@ describe('Content Security Policy', () => { expect(response.text).toContain(`