diff --git a/src/lib/__snapshots__/create-config.test.ts.snap b/src/lib/__snapshots__/create-config.test.ts.snap index 0064124bf73d..5fe12abf9b66 100644 --- a/src/lib/__snapshots__/create-config.test.ts.snap +++ b/src/lib/__snapshots__/create-config.test.ts.snap @@ -145,6 +145,7 @@ exports[`should create default config 1`] = ` "personalAccessTokensKillSwitch": false, "projectOverviewRefactorFeedback": false, "queryMissingTokens": false, + "removeUnsafeInlineStyleSrc": false, "resourceLimits": false, "responseTimeMetricsFix": false, "responseTimeWithAppNameKillSwitch": false, diff --git a/src/lib/middleware/secure-headers.ts b/src/lib/middleware/secure-headers.ts index 2cbe8be202ab..5eaa8926f3f3 100644 --- a/src/lib/middleware/secure-headers.ts +++ b/src/lib/middleware/secure-headers.ts @@ -5,6 +5,20 @@ import { hoursToSeconds } from 'date-fns'; const secureHeaders: (config: IUnleashConfig) => RequestHandler = (config) => { if (config.secureHeaders) { + const includeUnsafeInline = !config.flagResolver.isEnabled( + 'removeUnsafeInlineStyleSrc', + ); + const styleSrc = ["'self'"]; + if (includeUnsafeInline) { + styleSrc.push("'unsafe-inline'"); + } + styleSrc.push( + 'cdn.getunleash.io', + 'fonts.googleapis.com', + 'fonts.gstatic.com', + 'data:', + ...config.additionalCspAllowedDomains.styleSrc, + ); const defaultHelmet = helmet({ hsts: { maxAge: hoursToSeconds(24 * 365 * 2), // 2 non-leap years @@ -26,15 +40,7 @@ const secureHeaders: (config: IUnleashConfig) => RequestHandler = (config) => { 'fonts.gstatic.com', ...config.additionalCspAllowedDomains.fontSrc, ], - styleSrc: [ - "'self'", - "'unsafe-inline'", - 'cdn.getunleash.io', - 'fonts.googleapis.com', - 'fonts.gstatic.com', - 'data:', - ...config.additionalCspAllowedDomains.styleSrc, - ], + styleSrc, scriptSrc: [ "'self'", 'cdn.getunleash.io', diff --git a/src/lib/types/experimental.ts b/src/lib/types/experimental.ts index 98b6f938668a..2d8488c98ec0 100644 --- a/src/lib/types/experimental.ts +++ b/src/lib/types/experimental.ts @@ -65,7 +65,8 @@ export type IFlagKey = | 'resourceLimits' | 'extendedMetrics' | 'cleanApiTokenWhenOrphaned' - | 'allowOrphanedWildcardTokens'; + | 'allowOrphanedWildcardTokens' + | 'removeUnsafeInlineStyleSrc'; export type IFlags = Partial<{ [key in IFlagKey]: boolean | Variant }>; @@ -314,6 +315,10 @@ const flags: IFlags = { process.env.UNLEASH_EXPERIMENTAL_CLEAN_API_TOKEN_WHEN_ORPHANED, false, ), + removeUnsafeInlineStyleSrc: parseEnvVarBoolean( + process.env.UNLEASH_EXPERIMENTAL_REMOVE_UNSAFE_INLINE_STYLE_SRC, + false, + ), }; export const defaultExperimentalOptions: IExperimentalOptions = {