canvas 已被 computedStyleMap().get("background-image") 的跨源数据污染

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});
}

运行 这段代码 chrome 83,第一次加载代码,一切正常,但是当我在浏览器中刷新页面时,我得到了 console.log:

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

为什么以及如何解决?

在当前的 Chromium 实现中,CSSImageValue::WouldTaintOrigin 始终设置为 return true

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; }

如果在 canvas 上绘制这样的图像源后 能够获得 canvas 数据 ,那么请向 chromium 提交错误立即与团队联系,因为这将是一个安全问题。 (但我不能自己复制这个 Chrome 83 或任何其他分支)。

请注意,目前 HTML 规范仍不包括 CSSImageValue 作为潜在来源,但 the plan is that it will fall in the HTMLOrSVGImageElement branch of is-origin-clean 算法。所以 CSSImageValue 应该只在跨源请求的情况下污染 canvas,但是考虑到 API 的年轻化以及在所有这些中经常存储该信息的困难改变接口,实现者只是在安全方面犯了错误,只是一直将其标记为不安全,因为他们被允许处理他们认为不安全的任何来源。