Skip to content

Instantly share code, notes, and snippets.

@koto
Created February 9, 2021 11:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save koto/7ad3b636a48a4fa39760dd2b88187162 to your computer and use it in GitHub Desktop.
Save koto/7ad3b636a48a4fa39760dd2b88187162 to your computer and use it in GitHub Desktop.
// Sanitizer can produce TrustedHTML as long as its configuration respects sinks guarded by TT.
// (HTML sinks are only guarded because they themselves could bypass restrictions of script.src etc.)
// With the current sanitizer API (no XSS is possible via config), and current TT API (only native XSS sinks are guarded),
// Sanitizer can always produce a TrustedHTML.
trustedHTML = (new Sanitizer()).sanitizeToTrustedHTML('<div><script>removeme</script>') // yay!
// If Web APIs add new native XSS sinks, they should be added simultaneously to TT and Sanitizer
// Speculatively, in the future, if TT could guard other custom sinks in the DOM:
// E.g. let's imagine we can block [data-trustedscript-*] attributes like so:
// Perhaps this should work by default, and not be configurable, or the configuration is in the header.
trustedTypes.strawman.requireTrustedTypeForDataAttributesWithThePrefix('trustedscript', 'TrustedScript')
// From now on, the default sanitizer should not "just" produce TrustedHTML.
// Payloads that contain the restricted sinks should not be produced by the santiizer (it'd be a bypass).
// Throws a TT violation (or calls a default policy?)
trustedHTML = (new Sanitizer()).sanitizeToTrustedHTML('<div data-trustedscript-sneaky=evil></div>')
// Throws, just like el.innerHTML, or DOMParser.parseFromString (mabe call a default policy?)
nodes = (new Sanitizer()).sanitizeToNodes('<div data-trustedscript-sneaky=evil></div>')
// Doesn't _need_ to throw, but not throwing would be surprising. (maybe call a default policy?)
string = (new Sanitizer()).sanitizeToString('<div data-trustedscript-sneaky=evil></div>')
// But we can configure the sanitizer to respect TT and produce TrustedHTML again.
trustedHTML = (new Sanitizer({
blockAttributes: {"data-trustedscript-sneaky": ["*"]}
})).sanitizeToTrustedHTML('<div data-trustedscript-sneaky=evil></div>') // works, as no sink was touched.
@shhnjk
Copy link

shhnjk commented Feb 9, 2021

// Doesn't need to throw, but not throwing would be surprising. (maybe call a default policy?)
string = (new Sanitizer()).sanitizeToString('<div data-trustedscript-sneaky=evil></div>')

If we go with this solution, we should just create a method called sanitizeToHTML (which combines sanitizeToTrustedHTML and sanitizeToString together), and depending on the Trusted Types support, browser will return either string or TrustedHTML.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment