Understanding the HTML5 Canvas image security rules

There’s a common point of confusion regarding when one can use HTML5 Canvas getImageData() and toDataUrl() methods. Certain canvas conditions will cause these methods to throw a security error.

The rules for what one can and cannot do are laid out in the Canvas specification, though the reasoning behind them isn’t so obvious. The most typical violation is when a programmer calls ctx.drawImage() with an image that is from a different domain (than the page that the canvas is on) or an image that is on the local file system. When ctx.drawImage() is used in one of these two ways, the canvas internally sets its origin-clean flag to false.

From the moment a canvas has its origin-clean flag set to false, the getImageData() and toDataUrl() methods will throw security errors. There are a few less common cases where the origin-clean flag will be set to false, you can read about them in the spec here.

The reason for this security is to prevent something called information leakage. To see why this is a security issue, consider the following hypothetical situation:

Say you are on a work network and so you have access to internal, private company sites and your (private!) hard-drive. The private sites might be something like www.internal.myCompany.com and your hard drive would be accessible from urls like file:///C:/SomeOfMyPhotos/.

Now suppose you visited a website with a hidden canvas and while you were browsing the site that canvas was constantly calling drawImage() onto that canvas with urls that it was guessing might exist. These urls would be things like an image on the private subdomain:

www.internal.myCompany.com/secret/secret-plans.jpg

Or an image on your hard drive:

file:///C:/SomeOfMyPhotos/thatEmbarassingPhoto.png

The malicious site could keep trying different combinations of private-to-you urls until it found one that was actually a file. Then it would draw it to the canvas. Then it would get the imageData from the canvas and send it off to the server.

Voila! The malicious site owner now has your secret plans and your embarrassing photos, much without your consent.

Now we know that the above scenario is not very probable: In the real world, secret plans are almost always in PNG format whereas embarassing photos are almost universally in JPG format! But it stands that situations like the above could happen and so the security implications of canvas must take this into account.

I wrote a book on HTML5, including three chapters on Canvas! Buy it here.

  • Jarrod

    Love the reason why the scenario is not probable – made me smile.

  • Thomas Haratyk

    Hello, first I’d like to say thanks for your articles it is really good job. 
    I’m not sure that I understand everything in this article, does it mean if in my web application using canvas, I want the user to load a picture from his computer or from an external URL (like https://ssl.gstatic.com/images/logos/google_logo_41.png), let him draw onto it, and then save it in PNG to my server, I can’t ?? Thank you very much 

  • Lance

    I want to access something in the same domain… but with a different machine… ie m1.myserver.com and m2.myserver.com, seems reasonably secure?

    • http://www.simonsarris.com simonsarris

      Sometimes sites are hosted on domains like, for example:

      http://home.comcast.net/~heidi.quinn/all_stevensline.htm (just some random page I found)But what if that site tried to grab something from internal.comcast.net, effectively taking a file from a comcast employee (presumably they’d be able to access internal.comcast.net from their computer at work but its unavailable otherwise)

  • Mike

    This would only be a problem if canvas were capable of reading the local filesystem. If that is the case, who thought that would be a good idea?? Now, because of this, I can’t call toDataUrl on an external image which is already openly accessible!