Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make Angular working with restrictive Content Security Policy (CSP)

I cannot make base Angular2 (final) application works with the following restrictive CSP.

default-src 'none'; script-src 'self'; style-src 'self'; font-src 'self'; img-src 'self' data:; connect-src 'self' 

There are one unsafe-eval error in lang.js and two in zone.js. Could you provide a solution ?

Step to reproduce with Angular CLI

I have created a GitHub repository. You can also follow the instructions below.

Use the last Angular CLI with Webpack 6.0.8 and the new application created with the instructions below.

ng new csp-test 

Insert in the index.html the meta tag defining the following restrictive Content Security Policy.

<meta    http-equiv="Content-Security-Policy"    content="default-src 'none';script-src 'self';style-src 'self';font-src 'self';img-src 'self' data:;connect-src 'self'"> 

Then serve the application.

ng serve 

Access http://localhost:4200/, the page does not load since scripts are blocked by CSP.

Errors

Error in Chrome

lang.js

lang.js:335 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'". 

with the source code.

335: return new (Function.bind.apply(Function, [void 0].concat(fnArgNames.concat(fnBody))))().apply(void 0, fnArgValues); 

zone.js

zone.js:344 Unhandled Promise rejection: 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'".  ; Zone: <root> ; Task: Promise.then ; Value: 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'".  zone.js:346 Error: Uncaught (in promise): 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'".(…) 

with the source code.

343: if (rejection) { 344:     console.error('Unhandled Promise rejection:', rejection instanceof Error ? rejection.message : rejection, '; Zone:', e.zone.name, '; Task:', e.task && e.task.source, '; Value:', rejection, rejection instanceof Error ? rejection.stack : undefined); 345: } 346: console.error(e); 
like image 422
Nicolas Henneaux Avatar asked Aug 03 '16 04:08

Nicolas Henneaux


People also ask

What is CSP in angular?

Angular CSP is a security feature that makes your site less vulnerable to attacks like XSS. You can use this feature to specify whether your site should allow in-line JavaScript or not. In addition, you can specify policies for other content like AJAX, CSS, and iframe.


2 Answers

Edited answer for @angular/cli>=8.2

From this Github thread, one can use the index property in angular.json to control the generation of the application's HTML index:

build: {   ...   "configurations": {     "production": {       "index": {         "input": "src/index.production.html",          "output": "index.html"        },       ...     }   } } 

Original answer

I've found a way to have restrictive CSP on my production environment while still being able to use the JTI compliler for development.

  • Add a second file: index.production.html to the src folder.
  • Copy the contents of index.html to that file, and add the restrictive CSP header.
<meta http-equiv="Content-Security-Policy"  content="default-src 'none';   frame-src 'self';   script-src 'self';   style-src 'self' 'unsafe-inline';   font-src 'self';   img-src 'self' data:;   connect-src 'self'"> 
  • Then, add to your angular.json the following:
build: {   ...   "configurations": {     "production": {       "fileReplacements": [         {           "replace": "src/index.html",           "with": "src/index.production.html"         }       ],       ...     }   } } 

This makes sure that when you run a production build, it will use the index.production.html with the restrictive CSP, and when you're running it locally, you can use the JTI compiler.

like image 128
Jesse Avatar answered Sep 28 '22 10:09

Jesse


Using ahead-of-time compilation solves the problem. The following command can be used to build an application working with restrictive CSP.

ng build --prod 

To test it locally you can use

ng serve --prod 
like image 32
Nicolas Henneaux Avatar answered Sep 28 '22 09:09

Nicolas Henneaux