tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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>