Support Trusted Types API to prevent XSS attacks
Problem
Currently, html-dom-parser unsafely assigns strings to innerHtml. Browsers now support a method for developers to assert that any innerHtml has been sanitized and is safe to assign to innerHtml, in the form of TrustedTypes. See documentation here:
Suggested Solution
I can think of 2 ways to fix this:
- Allow the user to pass in a TrustedHTML object instead of a string. This would mean that the caller of html-dom-parser would do the sanitization, and then pass in a safe string into html-dom-parser.
- This strategy requires relaxing the check for
typeof "string"here in the code. However, we would also need to avoid any re-assigning of the html string, removing instances like this, which would make special character escapes hard to handle.
- This strategy requires relaxing the check for
- Allow the user to pass in a TrustedTypePolicy, and then
html-dom-parserwould runpolicy.createHtml(myString)before assigning anything toinnerHtml.
Keywords
security, trustedtypes, innerhtml
@ValerianClerc thanks for creating this issue! I'm open to a PR that implements this as long as it's backwards compatible and doesn't cause a breaking change.
@remarkablemark Awesome, I'll try to put something together this week!
Would you be open to me making a similar change in html-react-parser too?
@ValerianClerc yes, I'm open.
For your suggested solution, will the user pass it via the option argument? Something like:
parse('<br>', {
trustedHTML: ...
})
Yes I think that would be the best solution, passing in via option argument.
I think "option 2" in my proposal is likely to be the simplest to implement for the codebase, since I don't think that the TrustedHTML type in "option 1" supports re-assignment/modification that is currently being used for special character handling in html-dom-parser.
So it would be something like:
const policy = window.trustedTypes.createPolicy('myPolicy', {
createHTML: (html) => mySanitizeFunction(html)
})
parse('<br>', {
trustedTypePolicy: policy
})
And then inside the parsing code (domparser.ts), we would do something like this:
parseFromTemplate = (html: string, trustedTypePolicy?: TrustedTypePolicy): NodeList => {
const sanitizedHtml = trustedTypePolicy?.createHTML(html) ?? html
template.innerHTML = sanitizedHtml;
return template.content.childNodes;
};
@ValerianClerc sounds good