diff --git a/packages/@n8n/config/src/configs/security.config.ts b/packages/@n8n/config/src/configs/security.config.ts index 845132a4b3..e9cac862ed 100644 --- a/packages/@n8n/config/src/configs/security.config.ts +++ b/packages/@n8n/config/src/configs/security.config.ts @@ -32,4 +32,10 @@ export class SecurityConfig { // TODO: create a new type that parses and validates this string into a strongly-typed object @Env('N8N_CONTENT_SECURITY_POLICY') contentSecurityPolicy: string = '{}'; + + /** + * Whether to set the `Content-Security-Policy-Report-Only` header instead of `Content-Security-Policy`. + */ + @Env('N8N_CONTENT_SECURITY_POLICY_REPORT_ONLY') + contentSecurityPolicyReportOnly: boolean = false; } diff --git a/packages/@n8n/config/test/config.test.ts b/packages/@n8n/config/test/config.test.ts index ae133c15b1..b4a5f5b5a6 100644 --- a/packages/@n8n/config/test/config.test.ts +++ b/packages/@n8n/config/test/config.test.ts @@ -272,6 +272,7 @@ describe('GlobalConfig', () => { blockFileAccessToN8nFiles: true, daysAbandonedWorkflow: 90, contentSecurityPolicy: '{}', + contentSecurityPolicyReportOnly: false, }, executions: { pruneData: true, diff --git a/packages/cli/src/server.ts b/packages/cli/src/server.ts index 5ef6c75f50..af55a95d26 100644 --- a/packages/cli/src/server.ts +++ b/packages/cli/src/server.ts @@ -354,11 +354,13 @@ export class Server extends AbstractServer { errorMessage: 'The contentSecurityPolicy is not valid JSON.', }, ); + const cspReportOnly = Container.get(SecurityConfig).contentSecurityPolicyReportOnly; const securityHeadersMiddleware = helmet({ contentSecurityPolicy: isEmpty(cspDirectives) ? false : { useDefaults: false, + reportOnly: cspReportOnly, directives: { ...cspDirectives, },