(It seems that my problem is related to getting error `This document requires 'TrustedHTML' assignment` in chrome, but I'm using Angular v10 instead)
Description:
When I use the [innerHTML]="myVar"
directive on an Angular 10 (or below) project, with a strict CSP require-trusted-types-for 'script';
it fails with the message:
This document requires 'TrustedHTML' assignment. ERROR TypeError: Failed to set the 'innerHTML' property on 'Element': This document requires 'TrustedHTML' assignment.
How to reproduce:
[innerHTML]="someVar"
directive in a templaterequire-trusted-types-for 'script';
CSP headerWhat I tried:
After reading some sources on the trusted types, like :
I tried to use https://github.com/cure53/DOMPurify on my Angular project. Simply add the package, create an Angular pipe, and use it in the template.
The pipe can be created using the below code:
import { Pipe, PipeTransform } from '@angular/core';
import * as DOMPurify from 'dompurify';
@Pipe({
name: 'safeHtml'
})
export class SafeHtmlPipe implements PipeTransform {
transform(value: string): TrustedHTML {
return DOMPurify.sanitize(value, {RETURN_TRUSTED_TYPE: true});
}
}
And it can be used like this: [innerHTML]="myVar | safeHtml"
Of course, I checked the return with a console.log
, and it gives me a real TrustedHTML object.
New errors popped in Chrome console, so I had to add a new CSP header to authorize DOMPurify:
require-trusted-types-for 'script';trusted-types dompurify
After that, Chrome was happy to see a DOMPurify string manipulation.
However, the initial error re-emerges!
I don't understand what I missed - Chrome complaints about a TrustedHTML type in the innerHTML call, so I do a TrustedHTML transformation. After that Chrome wants an explicit authorization for dompurify, so I do it, and after that Chrome complaints again about a TrustedHTML type...
A way to avoid the error:
Add a CSP require-trusted-types-for 'script';trusted-types default
(source on https://w3c.github.io/webappsec-trusted-types/dist/spec/#default-policy-hdr)
Add a little snippet specific for the innerHTML method:
if (window.trustedTypes && window.trustedTypes.createPolicy) {
window.trustedTypes.createPolicy('default', {
createHTML: (string, sink) => string
});
}
Some tips here: https://github.com/angular/angular/pull/32353
Be careful with this approach, because it marks every assignment to innerHTML as trusted without making sure it is actually safe. In essence, it sidesteps the point of Trusted Types, as this approach no longer stops injection vulnerabilities (e.g., this.div.nativeElement.innerHTML = userInput).