Angular: how to set up Content-Security-Policy & Trusted Types?

2.4k views Asked by At

Having read the Angular security guidelines, I would like to:

Here is how I changed my index.html so far:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; style-src 'self' 'unsafe-inline';" />
    <meta http-equiv="Content-Security-Policy" content="trusted-types angular angular#unsafe-bypass; require-trusted-types-for 'script';" />

Right now, I have got a lot of errors in my console:

This document requires 'TrustedScript' assignment.
FooService EvalError: Refused to evaluate a string as JavaScript because this document requires 'Trusted Type' assignment.

My questions:

  • Is it OK to define the Content-Security-Policy twice/for the both:
    One for the "classic" CSP configuration, one for the trusted types?
    Does it make sense?
  • How do they relate with each other?
  • How do I make it work both locally and in production?
    • I understood that this configuration should probably be activated only in production environments (because of JIT),
      using a specific index.production.html file (see).
      I am not a big fan of duplicating the index.html just for two meta properties...
    • I also saw that I could use the headers property in my architect.serve.configurations.production,
      but I am not sure if it is better and/or equivalent
  • Should I even use the trusted-types?
    It is recommended by the Angular security guidelines, but still experimental

I read some interesting resources, but they do not show how to concretely use the CSP attribute.
I am using Angular 13.

2

There are 2 answers

0
Andrey K. On

Just add "safevalues": "^0.1.8" to dependencies and "@types/trusted-types": "^2.0.2" to devDependencies and use it in your code like this:

    import {unwrapHtmlForSink} from 'safevalues';
    import {createHtml} from 'safevalues/implementation/html_impl';
    ...
    this.r.setProperty(this.inputValue.nativeElement, 'innerHTML', unwrapHtmlForSink(createHtml('some_html')));
0
Halvor Sakshaug On

You can have multiple CSPs. All of them will be checked separately and your content need to pass all policies. You can have one intended for CSP level 2 and one for CSP level 3 (where level 2 browsers will ignore directives it doesn't understand).

I would recommend setting CSP as a response header. It is simpler to configure per environment and more features are available such as report-uri and frame-ancestors.

Trusted types adds another layer of security and I would implement it if possible after mastering the basic CSP.