v156 · canvas tainting

Taint matrix

One SVG containing a <foreignObject>, three URL schemes, three canvases. Each one is drawn and then read back with getImageData(); the verdict below each is whatever the browser actually did, including the SecurityError it threw.

Draw, then try to read back

Unticking the box draws plain SVG shapes instead. That is the control: without a foreignObject none of the three taints, which shows the rule is about foreign content and not about the URL scheme on its own. Each run builds three brand new canvases, because tainting is permanent for the life of a canvas — clearRect() does not undo it, and reusing one would carry the previous verdict forward.

http: (same origin)

not run

data:

not run

blob:

not run

Press Run to draw all three and read them back.

What each engine does

Canvas tainting for an SVG containing a foreignObject
schemeGeckoWebKitChrome ≤ 155Chrome 156+this browser
http:taintstaintstaintstaints
data:cleancleancleanclean
blob:cleantaintstaintsclean

The http: row is not a bug to be fixed: an SVG fetched over the network can reference content the page could not otherwise read, so tainting is the correct outcome. Only the blob: row changed, and only because a blob's contents came from the page in the first place.

code path

const image = new Image();
image.onload = () => {
  context.drawImage(image, 0, 0);
  try {
    context.getImageData(0, 0, 1, 1);   // throws if the canvas is tainted
    console.log("[taint] readable");
  } catch (error) {
    console.warn("[taint] tainted:", error.name);   // SecurityError
  }
};
image.src = URL.createObjectURL(new Blob([svg], { type: "image/svg+xml" }));

see also