Handling Content Security Policy (CSP) for React App, (styleSrc, scriptSrc - eval)

168 Views Asked by At

I would like to implement a more secure Content Security Policy (CSP) in my React application. I have utilized the following libraries in my application:

{
    "dependencies": {
        "@beam-australia/react-env": "^3.0.8",
        "@fortawesome/fontawesome-free": "^5.13.1",
        "@hookform/error-message": "^0.0.3",
        "@popperjs/core": "^2.5.2",
        "@testing-library/jest-dom": "^4.2.4",
        "@testing-library/react": "^9.3.2",
        "@testing-library/user-event": "^7.1.2",
        "@turf/turf": "^6.5.0",
        "axios": "^0.19.2",
        "axios-retry": "^3.1.9",
        "body-scroll-lock": "^3.1.5",
        "classnames": "^2.2.6",
        "d3": "^6.1.1",
        "date-fns": "^2.15.0",
        "eslint-config-prettier": "^6.11.0",
        "file-saver": "^2.0.5",
        "framer-motion": "^1.11.1",
        "helmet-csp": "^3.4.0",
        "jszip": "^3.10.0",
        "jszip-utils": "^0.1.0",
        "leaflet": "^1.7.1",
        "leaflet-draw": "^1.0.4",
        "lodash": "^4.17.19",
        "mobx": "^5.15.4",
        "mobx-react": "^6.2.2",
        "phoenix": "^1.5.4",
        "query-string": "^6.13.1",
        "react": "^16.13.1",
        "react-color": "^2.19.3",
        "react-day-picker": "^7.4.8",
        "react-device-detect": "^1.17.0",
        "react-dom": "^16.13.1",
        "react-dropzone": "^11.3.2",
        "react-hook-form": "6.15.6",
        "react-json-view": "^1.21.3",
        "react-lazyload": "^3.2.0",
        "react-leaflet": "^2.7.0",
        "react-leaflet-draw": "^0.19.0",
        "react-popper": "^2.2.3",
        "react-popper-tooltip": "^3.1.0",
        "react-router-dom": "^5.2.0",
        "react-scripts": "3.4.1",
        "react-select": "^3.1.0",
        "react-sortable-hoc": "^1.11.0",
        "react-sortablejs": "^2.1.0",
        "react-table": "^7.2.2",
        "react-time-picker": "^4.0.1",
        "serve": "^11.3.2",
        "shortid": "^2.2.15",
        "sortablejs": "^1.13.0",
        "styled-components": "^5.1.1"
    },
    "devDependencies": {
        "concurrently": "^5.2.0",
        "eslint-plugin-prettier": "^3.1.4",
        "eslint-plugin-react-hooks": "^4.0.8",
        "eslint-plugin-sort-imports-es6-autofix": "^0.5.0",
        "eslint-plugin-tailwind": "^0.2.0",
        "gulp": "^4.0.2",
        "gulp-postcss": "^8.0.0",
        "gulp-rename": "^2.0.0",
        "husky": "^4.2.5",
        "lint-staged": "^10.2.11",
        "postcss-import": "^12.0.1",
        "postcss-nested": "^4.2.3",
        "prettier": "^2.0.5",
        "tailwindcss": "1.4.6"
    },
}

I applied below csp restriction using helmet

directives: {
    defaultSrc: ["'self'"],
    scriptSrc: ["'self'", "'unsafe-inline'", "'unsafe-eval'"],
    connectSrc: ["'self'"],
    imgSrc: ["'self'"],
    styleSrc: ["'self'", "'unsafe-inline'"],
    frameAncestors: ["'self'"],
    formAction: ["'self'"]
  }

I remove "unsafe-eval" from scriptSrc. However, when I attempted to remove "unsafe-eval," I encountered the following error. [Updated] I got some clue of below issue on here https://github.com/Turfjs/turf/issues/261

Uncaught EvalError: Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "script-src 'self' 'unsafe-inline'".

    at new Function (<anonymous>)
    at i (turf.min.js:43:13355)
    at turf.min.js:43:13417
    at Bt (turf.min.js:43:5509)
    at turf.min.js:43:12336
    at Object.<anonymous> (turf.min.js:1:69)
    at Object.<anonymous> (2.4de531c1.chunk.js:2:1027584)
    at l (bootstrap:79:22)
    at 659 (main.c028a1fc.chunk.js:1:353591)
    at l (bootstrap:79:22)
i @ turf.min.js:43
(anonymous) @ turf.min.js:43
Bt @ turf.min.js:43
(anonymous) @ turf.min.js:43
(anonymous) @ turf.min.js:1
(anonymous) @ 2.4de531c1.chunk.js:2
l @ bootstrap:79
659 @ main.c028a1fc.chunk.js:1
l @ bootstrap:79
426 @ main.c028a1fc.chunk.js:1
l @ bootstrap:79
t @ bootstrap:45
r @ bootstrap:32
(anonymous) @ main.c028a1fc.chunk.js:1
Show 5 more frames
Show less

When I remove 'unsafe-inline' from scriptSrc: ["'self'", "'unsafe-eval'"], everything works correctly. However, when I remove 'unsafe-inline' from styleSrc: ["'self'], I encounter the following error.

Refused to apply inline style because it violates the following Content Security Policy directive: "style-src 'self'". Either the 'unsafe-inline' keyword, a hash ('sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU='), or a nonce ('nonce-...') is required to enable inline execution.
j @ constants.js:4
t @ constants.js:4
e.getTag @ Sheet.js:44
e.insertRules @ Sheet.js:79
t.generateAndInjectStyles @ isStaticRules.js:6
(anonymous) @ Keyframes.js:20
(anonymous) @ Keyframes.js:20
S @ Keyframes.js:20
Xo @ react-dom.production.min.js:153
ka @ react-dom.production.min.js:173
vs @ react-dom.production.min.js:265
lu @ react-dom.production.min.js:246
su @ react-dom.production.min.js:246
Js @ react-dom.production.min.js:239
(anonymous) @ react-dom.production.min.js:123
e.unstable_runWithPriority @ scheduler.production.min.js:19
Vi @ react-dom.production.min.js:122
qi @ react-dom.production.min.js:123
Wi @ react-dom.production.min.js:122
vu @ react-dom.production.min.js:257
e.unstable_runWithPriority @ scheduler.production.min.js:19
Vi @ react-dom.production.min.js:122
gu @ react-dom.production.min.js:257
(anonymous) @ react-dom.production.min.js:256
B @ scheduler.production.min.js:17
x.port1.onmessage @ scheduler.production.min.js:14
Show 18 more frames
Show less

I also tried using INLINE_RUNTIME_CHUNK=false like this below also no help. "build": "npm run build:css && INLINE_RUNTIME_CHUNK=false react-scripts build"

I was able to fix the issue with inline styles used in my application. However, I noticed that some libraries are using inline style syntax, and now I am somewhat lost with no idea how to address these.

0

There are 0 best solutions below