If you set img.crossOrigin attribute before the img.src, it taints a canvas when painted
Reported by
simon.sa...@gmail.com,
Jan 4 2017
|
|||||
Issue descriptionUserAgent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2970.0 Safari/537.36 Steps to reproduce the problem: 1. Create HTML Image and Canvas 2. On image load, paint to canvas context 3. Set img.src = SomeCrossOriginCapableImage 4. Set img.crossOrigin = "anonymous" 5. The image loads and paints 6. A while later, you check the canvas with getImageData 7. Security error from tainted canvas What is the expected behavior? The order of #3 and #4 should not matter, so long as both are set before painting. What went wrong? #7. Did this work before? N/A Chrome version: 57.0.2970.0 Channel: dev OS Version: 10.0 Flash Version: Shockwave Flash 24.0 r0 For what its worth, this code works on Firefox.
,
Jan 4 2017
I see, the caching tie-in may also explain a second bug scenario that I haven't yet isolated. In the canvas library I'm writing, the CORS works just fine for an image source unless that image is also present in the DOM as an <img>, even if that instance in the DOM has its crossorigin flag set: <img src="https://i.imgur.com/fHyEMsl.jpg" crossOrigin='anonymous'> Simply the presence of it causes the totally separate painting of an in-memory img (that happens to use the same source URL) to a canvas to result in a tainted canvas. Hopefully these are related and fixed by the same thing. I cannot yet reproduce this in a simpler case.
,
May 4 2017
I think that this and crbug.coc/718352 are probably the same issue.
,
May 9 2017
Quickly triaging with initial guess (might be wrong though): The root cause is ImageLoader::UpdateFromElement() is NOT called when crossorigin attribute is updated. ImageLoader::UpdateFromElement() is called from HTMLImageElement::SelectSourceURL() from HTMLImageElement::ParseAttribute() for src/srcset/sizes attribute changes, but not crossorigin. According to the spec (https://html.spec.whatwg.org/#relevant-mutations), crossorigin attribute changes also trigger UpdateFromElement(). > Comment #2: > the CORS works just fine for an image source unless that image is also present in the DOM as an <img>, even if that instance in the DOM has its crossorigin flag set Perhaps this is because UpdateFromElement() start loading synchronously when the URL exists on MemoryCache (no matter whether it can be reused or not; just checks the URL and error status, see ImageLoader::ShouldLoadImmediately()). When ShouldLoadImmediately() returns true, the crossorigin attribute is checked immediately and we start the image loading using the crossorigin attribute at the time img.src is set (i.e. not set in this case). Otherwise, ImageLoader starts the loading asynchronously, and thus the crossorigin attribute is checked AFTER the JavaScript block is completed, i.e. after crossorigin is set. Issue 718352 and CORS implementation looks unrelated. Removing SecurityFeature>CORS. Added Blink>Image as this looks related to ImageLoader.
,
Oct 13 2017
,
Oct 13 2017
After Issue 774706 is fixed, the canvas is not tainted. However, two requests are sent to the network: (1) a no-cors request which is sent synchronously when img.src is set, and (2) a crossorigin request which is sent synchronously when img.crossorigin is set. This is because ImageLoader::ShouldLoadImmediately() return true. I feel ImageLoader::ShouldLoadImmediately() should always return true to enable us to merge multiple changes to <img> attributes into at most one network request and at most one image update, but this will need further investigation. With the fix for Issue 774706 and forcing ImageLoader::ShouldLoadImmediately() to always return false fixes the test case provided here: the canvas is not tainted, and one network request is sent to network if the Resource is not on MemoryCache, and one MemoryCache hit when on MemoryCache.
,
Oct 14 2017
(You said both "should always return true" and "should always return false" in the last two paragraphs - I'll assume you only meant the latter.) Isn't the problem that, in ShouldLoadImmediately - which is essentially our "in list of available images", we check if the URL is cached, but does not consider the CORS mode of the resource (which the actual fetch will.) Per spec the "key" used to perform the lookup in the "list of available images" also contains the CORS mode, so I'm thinking that this is the missing bit here? WDYT? |
|||||
►
Sign in to add a comment |
|||||
Comment 1 by junov@chromium.org
, Jan 4 2017Status: Available (was: Unconfirmed)