javascriptgoogle-chromecanvasbackground-imagecssom

The canvas has been tainted by cross-origin data with computedStyleMap().get("background-image")


<div id='img3'>background-image with this</div>
#img3 {
  background-image: url("../icons/we-flow.png");
}
var img = img3.computedStyleMap().get("background-image");
//img=img1;
var canvas=document.createElement('canvas');
img.crossOrigin="Anonymous";
var ctx=canvas.getContext('2d');
try {
  ctx.drawImage(img, 0, 0);
  var data=ctx.getImageData(0, 0, canvas.width, canvas.height).data;
}catch (error) {
  console.log('refresh page will get this', img.toString(), {error, img});
}

run this code with chrome 83, first time load the code, everything is ok, but when I refresh the page in browser, I got the console.log:

DOMException: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data.

why and how can i fix it?


Solution

  • In the current Chromium implementation, CSSImageValue::WouldTaintOrigin is set to return true, always.

    https://github.com/chromium/chromium/blob/master/third_party/blink/renderer/core/css/cssom/css_style_image_value.h#L32

     bool WouldTaintOrigin() const final { return true; }
    

    If you are able to get the canvas data after you painted such an image source on the canvas, then please file a bug to chromium's team right away as it would be a security issue. (But I can't reproduce this on my own Chrome 83 nor any other branches).

    Note that currently HTML specs still don't include CSSImageValue as a potential source, but the plan is that it will fall in the HTMLOrSVGImageElement branch of is-origin-clean algo. So CSSImageValue should only taint the canvas in case of cross-origin request, but given the youth of the APIs and the difficulty it would be to store that information in all these often changing interfaces, implementers just erred on the side of safety by simply marking it as unsafe all the time, as they are allowed to do with any source they consider unsafe.