fetch-canvas-tainting-double-write.https.html (2577B)
1 <!DOCTYPE html> 2 <script src="/resources/testharness.js"></script> 3 <script src="/resources/testharnessreport.js"></script> 4 <script src="/common/get-host-info.sub.js"></script> 5 <script src="resources/test-helpers.sub.js"></script> 6 <meta charset="utf-8"> 7 <title>canvas tainting when written twice</title> 8 <script> 9 function loadImage(doc, url) { 10 return new Promise((resolve, reject) => { 11 const image = doc.createElement('img'); 12 image.onload = () => { resolve(image); } 13 image.onerror = () => { reject('failed to load: ' + url); }; 14 image.src = url; 15 }); 16 } 17 18 // Tests that a canvas is tainted after it's written to with both a clear image 19 // and opaque image from the same URL. A bad implementation might cache the 20 // info of the clear image and assume the opaque image is also clear because 21 // it's from the same URL. See https://crbug.com/907047 for details. 22 promise_test(async (t) => { 23 // Set up a service worker and a controlled iframe. 24 const script = 'resources/fetch-canvas-tainting-double-write-worker.js'; 25 const scope = 'resources/fetch-canvas-tainting-double-write-iframe.html'; 26 const registration = await service_worker_unregister_and_register( 27 t, script, scope); 28 t.add_cleanup(() => registration.unregister()); 29 await wait_for_state(t, registration.installing, 'activated'); 30 const iframe = await with_iframe(scope); 31 t.add_cleanup(() => iframe.remove()); 32 33 // Load the same cross-origin image URL through the controlled iframe and 34 // this uncontrolled frame. The service worker responds with a same-origin 35 // image for the controlled iframe, so it is cleartext. 36 const imagePath = base_path() + 'resources/fetch-access-control.py?PNGIMAGE'; 37 const imageUrl = get_host_info()['HTTPS_REMOTE_ORIGIN'] + imagePath; 38 const clearImage = await loadImage(iframe.contentDocument, imageUrl); 39 const opaqueImage = await loadImage(document, imageUrl); 40 41 // Set up a canvas for testing tainting. 42 const canvas = document.createElement('canvas'); 43 const context = canvas.getContext('2d'); 44 canvas.width = clearImage.width; 45 canvas.height = clearImage.height; 46 47 // The clear image and the opaque image have the same src URL. But... 48 49 // ... the clear image doesn't taint the canvas. 50 context.drawImage(clearImage, 0, 0); 51 assert_true(canvas.toDataURL().length > 0); 52 53 // ... the opaque image taints the canvas. 54 context.drawImage(opaqueImage, 0, 0); 55 assert_throws_dom('SecurityError', () => { canvas.toDataURL(); }); 56 }, 'canvas is tainted after writing both a non-opaque image and an opaque image from the same URL'); 57 </script>