CSP Security Header Issues with Cesium in React Application

I am encountering loading errors with Cesium in our React frontend when applying Content Security Policy (CSP) rules via Webpack. Notably, when the CSP is inactive, Cesium visualizations function smoothly.

CSP Configuration:
I’ve implemented the following relaxed CSP using CspHtmlWebpackPlugin:

new CspHtmlWebpackPlugin({
  'default-src': "'self'",
  'script-src': ["'self'", "'unsafe-eval'", "*.virtualearth.net"],
  'worker-src': ["'self'", "blob:"],
  'object-src': "'none'",
  'style-src': ["'self'", "'unsafe-inline'"],
  'connect-src': [
    "'self'",
    "https://nominatim.openstreetmap.org",
    "https://example.com",
    "*.virtualearth.net",
    "https://login.microsoftonline.com",
    "*.cesium.com",
    "http://localhost:8084"
  ],
  'img-src': ["'self'", "data:", "*.virtualearth.net"]
}, {
  enabled: true,
  nonceEnabled: {
    'style-src': false,
    'script-src': false,
  }
}),

Alternatively, I tried a more relaxed configuration:

new CspHtmlWebpackPlugin({
  'default-src': ["*", "blob:", "data:", "'unsafe-eval'", "*.virtualearth.net", "*.cesium.com"],
  'base-uri': "'self'",
  'script-src': ["*", "blob:", "data:", "'unsafe-eval'", "'unsafe-inline'", "*.virtualearth.net", "*.cesium.com", "webpack:"],
  'worker-src': ["*", "blob:", "data:", "'unsafe-eval'", "'unsafe-inline'", "*.virtualearth.net", "*.cesium.com"],
  'media-src': ["*", "blob:", "data:", "*.virtualearth.net", "*.cesium.com"],
  'object-src': ["'unsafe-eval'", "*.virtualearth.net"],
  'style-src': ["*", "'unsafe-inline'", "'unsafe-eval'"],
  'connect-src': [
    "*",
    "data:",
    "blob:",
    "webpack:",
    "https://nominatim.openstreetmap.org",
    "https://example.com",
    "*.virtualearth.net",
    "https://login.microsoftonline.com",
    "*.cesium.com",
    "http://localhost:8084",
    "http://localhost:9000"
  ],
  'img-src': ["*", "data:", "blob:", "*.virtualearth.net", "*.cesium.com"],
  'font-src': ["*", "blob:", "data:"],
  'form-action': "https://login.microsoftonline.com"
}, {
  enabled: true,
  nonceEnabled: {
    'style-src': false,
    'script-src': false,
  }
}),

Errors:
With both configurations, I receive the following errors in the console:

In both above cases, the following Cesium errors appeared:

[Cesium WebGL] Fragment shader compile log:
overrideMethod @ console.js:288
createAndLinkProgram @ ShaderProgram.js:247
reinitialize @ ShaderProgram.js:470
initialize @ ShaderProgram.js:463
push../node_modules/@cesium/engine/Source/Renderer/ShaderProgram.js.ShaderProgram._bind @ ShaderProgram.js:542
beginDraw @ Context.js:1291
push../node_modules/@cesium/engine/Source/Renderer/Context.js.Context.draw @ Context.js:1397
push../node_modules/@cesium/engine/Source/Renderer/DrawCommand.js.DrawCommand.execute @ DrawCommand.js:608
push../node_modules/@cesium/engine/Source/Scene/GlobeDepth.js.GlobeDepth.executeCopyColor @ GlobeDepth.js:341
push../node_modules/@cesium/engine/Source/Scene/Scene.js.Scene.resolveFramebuffers @ Scene.js:3533
render @ Scene.js:3727
tryAndCatchError @ Scene.js:3745
push../node_modules/@cesium/engine/Source/Scene/Scene.js.Scene.render @ Scene.js:3835
push../node_modules/@cesium/engine/Source/Widget/CesiumWidget.js.CesiumWidget.render @ CesiumWidget.js:802
render @ CesiumWidget.js:41
requestAnimationFrame
render @ CesiumWidget.js:42
requestAnimationFrame
render @ CesiumWidget.js:42
requestAnimationFrame
render @ CesiumWidget.js:42
requestAnimationFrame
render @ CesiumWidget.js:42
requestAnimationFrame
render @ CesiumWidget.js:42
requestAnimationFrame
render @ CesiumWidget.js:42
requestAnimationFrame
render @ CesiumWidget.js:42
requestAnimationFrame
render @ CesiumWidget.js:42
requestAnimationFrame
render @ CesiumWidget.js:42
requestAnimationFrame
render @ CesiumWidget.js:42
requestAnimationFrame
render @ CesiumWidget.js:42
requestAnimationFrame
render @ CesiumWidget.js:42
requestAnimationFrame
render @ CesiumWidget.js:42
requestAnimationFrame
render @ CesiumWidget.js:42
requestAnimationFrame
render @ CesiumWidget.js:42
requestAnimationFrame
startRenderLoop @ CesiumWidget.js:68
set @ CesiumWidget.js:581
CesiumWidget @ CesiumWidget.js:371
Viewer @ Viewer.js:480
create @ resium.mjs:2909
(anonymous) @ resium.mjs:834
(anonymous) @ resium.mjs:869
commitHookEffectListMount @ react-dom.development.js:23189
commitLayoutEffectOnFiber @ react-dom.development.js:23307
commitLayoutMountEffects_complete @ react-dom.development.js:24727
commitLayoutEffects_begin @ react-dom.development.js:24713
commitLayoutEffects @ react-dom.development.js:24651
commitRootImpl @ react-dom.development.js:26862
commitRoot @ react-dom.development.js:26721
finishConcurrentRender @ react-dom.development.js:26020
performConcurrentWorkOnRoot @ react-dom.development.js:25848
workLoop @ scheduler.development.js:266
flushWork @ scheduler.development.js:239
performWorkUntilDeadline @ scheduler.development.js:533
Show 49 more frames
Show less
12:26:59.997 console.js:288 [Cesium WebGL] Fragment shader source:
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
precision highp int;
#else
precision mediump float;
precision mediump int;
#define highp mediump
#endif

#define OES_texture_float_linear

#define OES_texture_float

#line 0

#line 0
uniform sampler2D colorTexture;

varying vec2 v_textureCoordinates;

void main()
{
gl_FragColor = texture2D(colorTexture, v_textureCoordinates);
}

overrideMethod @ console.js:288
createAndLinkProgram @ ShaderProgram.js:248
reinitialize @ ShaderProgram.js:470
initialize @ ShaderProgram.js:463
push../node_modules/@cesium/engine/Source/Renderer/ShaderProgram.js.ShaderProgram._bind @ ShaderProgram.js:542
beginDraw @ Context.js:1291
push../node_modules/@cesium/engine/Source/Renderer/Context.js.Context.draw @ Context.js:1397
push../node_modules/@cesium/engine/Source/Renderer/DrawCommand.js.DrawCommand.execute @ DrawCommand.js:608
push../node_modules/@cesium/engine/Source/Scene/GlobeDepth.js.GlobeDepth.executeCopyColor @ GlobeDepth.js:341
push../node_modules/@cesium/engine/Source/Scene/Scene.js.Scene.resolveFramebuffers @ Scene.js:3533
render @ Scene.js:3727
tryAndCatchError @ Scene.js:3745
push../node_modules/@cesium/engine/Source/Scene/Scene.js.Scene.render @ Scene.js:3835
push../node_modules/@cesium/engine/Source/Widget/CesiumWidget.js.CesiumWidget.render @ CesiumWidget.js:802
render @ CesiumWidget.js:41
requestAnimationFrame
render @ CesiumWidget.js:42
requestAnimationFrame
render @ CesiumWidget.js:42
requestAnimationFrame
render @ CesiumWidget.js:42
requestAnimationFrame
render @ CesiumWidget.js:42
requestAnimationFrame
render @ CesiumWidget.js:42
requestAnimationFrame
render @ CesiumWidget.js:42
requestAnimationFrame
render @ CesiumWidget.js:42
requestAnimationFrame
render @ CesiumWidget.js:42
requestAnimationFrame
render @ CesiumWidget.js:42
requestAnimationFrame
render @ CesiumWidget.js:42
requestAnimationFrame
render @ CesiumWidget.js:42
requestAnimationFrame
render @ CesiumWidget.js:42
requestAnimationFrame
render @ CesiumWidget.js:42
requestAnimationFrame
render @ CesiumWidget.js:42
requestAnimationFrame
render @ CesiumWidget.js:42
requestAnimationFrame
startRenderLoop @ CesiumWidget.js:68
set @ CesiumWidget.js:581
CesiumWidget @ CesiumWidget.js:371
Viewer @ Viewer.js:480
create @ resium.mjs:2909
(anonymous) @ resium.mjs:834
(anonymous) @ resium.mjs:869
commitHookEffectListMount @ react-dom.development.js:23189
commitLayoutEffectOnFiber @ react-dom.development.js:23307
commitLayoutMountEffects_complete @ react-dom.development.js:24727
commitLayoutEffects_begin @ react-dom.development.js:24713
commitLayoutEffects @ react-dom.development.js:24651
commitRootImpl @ react-dom.development.js:26862
commitRoot @ react-dom.development.js:26721
finishConcurrentRender @ react-dom.development.js:26020
performConcurrentWorkOnRoot @ react-dom.development.js:25848
workLoop @ scheduler.development.js:266
flushWork @ scheduler.development.js:239
performWorkUntilDeadline @ scheduler.development.js:533
Show 49 more frames
Show less
12:27:00.008 console.js:288 An error occurred while rendering. Rendering has stopped.
RuntimeError: Fragment shader failed to compile. Compile log:
Error
at new RuntimeError (http://localhost:9000/app/vendors.bundle.js:378363:11)
at createAndLinkProgram (http://localhost:9000/app/vendors.bundle.js:446813:9)
at reinitialize (http://localhost:9000/app/vendors.bundle.js:447017:19)
at initialize (http://localhost:9000/app/vendors.bundle.js:447010:3)
at push../node_modules/@cesium/engine/Source/Renderer/ShaderProgram.js.ShaderProgram._bind (http://localhost:9000/app/vendors.bundle.js:447089:3)
at beginDraw (http://localhost:9000/app/vendors.bundle.js:440391:17)
at push../node_modules/@cesium/engine/Source/Renderer/Context.js.Context.draw (http://localhost:9000/app/vendors.bundle.js:440497:3)
at push../node_modules/@cesium/engine/Source/Renderer/DrawCommand.js.DrawCommand.execute (http://localhost:9000/app/vendors.bundle.js:442716:11)
at push../node_modules/@cesium/engine/Source/Scene/GlobeDepth.js.GlobeDepth.executeCopyColor (http://localhost:9000/app/vendors.bundle.js:494533:28)
at push../node_modules/@cesium/engine/Source/Scene/Scene.js.Scene.resolveFramebuffers (http://localhost:9000/app/vendors.bundle.js:588300:16)

Dependencies:
We are using the following versions:

Cesium: 1.100.0
Resium: 1.16.1
CSP HTML Webpack Plugin: 5.1.0
Webpack: 5.75.0
React: 18.2.0

Environment:
Browser: Chrome Version 129.0.6668.71 (Official Build) (32-bit)
Operating System: Windows 10 Pro

Can anyone help me with what I’m doing wrong?

Thank you for your time.

Hi @dk13011 ,
Thanks for your post and welcome to the Cesium community! I’m sorry you are having an issue getting your CSP setup to work with Cesium and Webpack.

We have a demo for Cesium and Webpack GitHub - CesiumGS/cesium-webpack-example: The minimal recommended setup for an application using Cesium with Webpack., I was able to add the CSPs you shared to the webpack (v5) settings in the app and it was able to startup and load data to the Cesium globe. This might be a useful reference for debugging.

Since you are using Resium, I should mention that Resium is a third-party tool - which while useful for lots of developers - is not officially endorsed or used internally at Cesium. We are happy to support any CesiumJS related issues, but Resium issues should go to the Resium developers. That might be the case here.

One item that jumps out is that your app is using a slightly old version of Cesium 1.100.0 from 2022-12-01, is it possible to upgrade?

Please let me know if the Cesium/Webpack tutorial or upgrading is helpful or if you would like more assistance.

Thanks!
Luke