fix(core): Remove inline JS from FE for more secure CSP (#17195)

This commit is contained in:
Iván Ovejero
2025-07-15 11:00:00 +02:00
committed by GitHub
parent 61e2e34caa
commit fc3129e378
3 changed files with 20 additions and 23 deletions

View File

@@ -13,6 +13,8 @@ import replaceStream from 'replacestream';
import { pipeline } from 'stream/promises';
import { z } from 'zod';
import { BaseCommand } from './base-command';
import { ActiveExecutions } from '@/active-executions';
import { ActiveWorkflowManager } from '@/active-workflow-manager';
import config from '@/config';
@@ -32,8 +34,6 @@ import { UrlService } from '@/services/url.service';
import { WaitTracker } from '@/wait-tracker';
import { WorkflowRunner } from '@/workflow-runner';
import { BaseCommand } from './base-command';
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const open = require('open');
@@ -164,9 +164,8 @@ export class Start extends BaseCommand<z.infer<typeof flagsSchema>> {
}
};
await compileFile('index.html');
const files = await glob('**/*.{css,js}', { cwd: EDITOR_UI_DIST_DIR });
await Promise.all(files.map(compileFile));
await Promise.all([compileFile('index.html'), ...files.map(compileFile)]);
}
async init() {

View File

@@ -1,3 +1,4 @@
import { CLI_DIR, EDITOR_UI_DIST_DIR, inE2ETests, N8N_VERSION } from '@/constants';
import { inDevelopment, inProduction } from '@n8n/backend-common';
import { SecurityConfig } from '@n8n/config';
import { Time } from '@n8n/constants';
@@ -14,7 +15,6 @@ import { resolve } from 'path';
import { AbstractServer } from '@/abstract-server';
import config from '@/config';
import { CLI_DIR, EDITOR_UI_DIST_DIR, inE2ETests, N8N_VERSION } from '@/constants';
import { ControllerRegistry } from '@/controller.registry';
import { CredentialsOverwrites } from '@/credentials-overwrites';
import { MessageEventBus } from '@/eventbus/message-event-bus/message-event-bus';
@@ -278,19 +278,21 @@ export class Server extends AbstractServer {
ResponseHelper.send(async () => frontendService.getModuleSettings()),
);
// Return Sentry config as a static file
this.app.get(`/${this.restEndpoint}/sentry.js`, (_, res) => {
res.type('js');
res.write('window.sentry=');
res.write(
JSON.stringify({
this.app.get(`/${this.restEndpoint}/config.js`, (_req, res) => {
const frontendSentryConfig = JSON.stringify({
dsn: this.globalConfig.sentry.frontendDsn,
environment: process.env.ENVIRONMENT || 'development',
serverName: process.env.DEPLOYMENT_NAME,
release: `n8n@${N8N_VERSION}`,
}),
);
res.end();
});
const frontendConfig = [
`window.BASE_PATH = '${this.globalConfig.path}';`,
`window.REST_ENDPOINT = '${this.globalConfig.endpoints.rest}';`,
`window.sentry = ${frontendSentryConfig};`,
].join('\n');
res.type('application/javascript');
res.send(frontendConfig);
});
}

View File

@@ -6,11 +6,7 @@
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<link rel="icon" href="/favicon.ico" />
<style>@media (prefers-color-scheme: dark) { body { background-color: rgb(45, 46, 46) } }</style>
<script type="text/javascript">
window.BASE_PATH = '/{{BASE_PATH}}/';
window.REST_ENDPOINT = '{{REST_ENDPOINT}}';
</script>
<script src="/{{REST_ENDPOINT}}/sentry.js"></script>
<script src="/{{REST_ENDPOINT}}/config.js"></script>
<script>!function(t,e){var o,n,p,r;e.__SV||(window.posthog=e,e._i=[],e.init=function(i,s,a){function g(t,e){var o=e.split(".");2==o.length&&(t=t[o[0]],e=o[1]),t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}(p=t.createElement("script")).type="text/javascript",p.async=!0,p.src=s.api_host+"/static/array.js",(r=t.getElementsByTagName("script")[0]).parentNode.insertBefore(p,r);var u=e;for(void 0!==a?u=e[a]=[]:a="posthog",u.people=u.people||[],u.toString=function(t){var e="posthog";return"posthog"!==a&&(e+="."+a),t||(e+=" (stub)"),e},u.people.toString=function(){return u.toString(1)+".people (stub)"},o="capture identify alias people.set people.set_once set_config register register_once unregister opt_out_capturing has_opted_out_capturing opt_in_capturing reset isFeatureEnabled getFeatureFlag onFeatureFlags reloadFeatureFlags".split(" "),n=0;n<o.length;n++)g(u,o[n]);e._i.push([i,s,a])},e.__SV=1)}(document,window.posthog||[])</script>
<title>n8n.io - Workflow Automation</title>