d3 / d3

Bring data to life with SVG, Canvas and HTML. :bar_chart::chart_with_upwards_trend::tada:
https://d3js.org
ISC License
109.06k stars 22.86k forks source link

TrustedTypePolicy.createHTML() in d3.svg #3951

Open jeffemandel opened 1 week ago

jeffemandel commented 1 week ago

I am using d3.svg to import svg images. I recently added require-trusted-types-for 'script'; to my CSP, and now I get this error:

[Report Only] This document requires 'TrustedHTML' assignment.

The stack trace points me to xml.js, which has:

function parser(type) {
  return (input, init) => text(input, init)
    .then(text => (new DOMParser).parseFromString(text, type));
}

The problem is that the text passed to parseFromString needs to be sanitized with some sort of TrustedTypePolicy. This works:

    const svgFile = myPolicy.createScriptURL(svgURL);
    const svg = await fetch(svgFile)
        .then(res => res.text())
        .then(text => {
            const svg = (new DOMParser).parseFromString(myPolicy.createHTML(text), 'image/svg+xml');
            return svg;
        })

Where:

const myPolicy = trustedTypes.createPolicy('mypolicy', {
  createHTML: (string) => dompurify.sanitize(string),
  createScriptURL: (s) => {
    if (typeof (s) == URL) {
      if (!url.origin.match(baseOrigin)) {
        throw new Error("Invalid origin");
      } else {
        return s;
      }
    }
}

This probably affects all of the routines in d3-fetch, at least for the createScriptURL.

mbostock commented 1 week ago

It probably doesn’t make sense to use d3-fetch for this. The implementation is pretty trivial on top of the Fetch API, so just use the Fetch API directly?

jeffemandel commented 1 week ago

Correct, but as trustedTypes become more prevalent, it might be nice to make it easier to be in compliance.