HTML5 Canvas getImageData - Security Issue - javascript

I am building a web app which reads an image through the FileReader API, and then displays it on a Canvas. After that, I re-color the image by going pixel-by-pixel after making the .getImageData call on the canvas, as shown below:
// Color Image on Canvas
ctx = document.getElementById('my_canvas').getContext('2d');
var img_px = ctx.getImageData(0,0,canv_w,canv_h);
img_px = colorImage(img_px,red,green,blue);
ctx.putImageData(img_px,0,0);
colorImage() is a function I've written that changes the pixel values given a corresponding RGB color code, and it definitely does work. The above snippet of code does work when I am loading an image locally, but it does not when I try to access an image from an online server, like a public Dropbox account. Firefox is telling me it's a security issue; is there a way to get around it?

I believe that this is a Cross Origin Resource Sharing CORS (security) issue.
See HTML5 Canvas getImageData and Same Origin Policy
The gist is, requests to images from external domains could inherently supply the user's authentication cookies, etc, allowing your javascript to access their potentially protected images and assets. While you can reference them, via <img>, CORS was established as a security protocol to prevent you from programmatically reading (and perhaps storing) the pixel data.
The Dropbox API supports CORS as of mid August, 2012. You may be able to accomplish what you want using their API once users properly authenticate.
https://github.com/dropbox/dropbox-js/blob/master/doc/getting_started.md

Related

What are security concerns around use of canvas.toDataURL?

What security threads would canvas.toDataURL generate in general? What measures we have to take to make use of it secure and thread free to our website?
In the following links there are discussions around security error that .toDataURL raises if the image is not hosted locally, but why is that?
canvas.toDataURL() causing a security error
Capture HTML Canvas as gif/jpg/png/pdf?
You may be aware of the same-origin policy. In essence, it's a security mechanism employed by browsers to make sure that only scripts that originate from the same site that the user is visiting are allowed to run without restrictions and access the DOM.
You could disguise a script as an image, for example you could store each group of 4 characters in the script in a pixel (one byte per channel), then read the pixels of that image to reconstruct the script.
This is why the same-origin policy applies to images too: if you draw images from a different domain into a canvas on your web page, there is a limit to what you can do with your canvas if you have drawn cross-origin images into it. For example, you can't inspect its pixels.
Now imagine that you could use canvas.toDataURL() to generate a data url from your cross-origin canvas. While your browser knows that your canvas contains cross-origin content, a data URL is just that: a URL. So there is no sure way of knowing that it has originated from a different domain in some way, and it could be potentially used to bypass the whole same-origin thing. As an example, you could create a new img and use the data URL as its src.

Vintage.js: remote images

Plugin only applies filter to files on my server, but with remote images:
Unable to get image data from canvas because the canvas has been tainted by cross-origin data.
How to fix it?
The error you are receiving is part of the browser's built-in security mechanisms to prevent hackers from using remote data to manipulate sites. You can't get around it (and if you could, it would be a major security hole that the browser makers would be very quick to fix)
To confirm this, the same question has already been asked on the Vinatge.js website (as a github issue ticket), and the answer given by the Vinatge.js author was that it isn't possible to load remote images.
Sorry to disappoint you.
The work-around given was to use a proxy loader on your own server to load the images so that they are not given to the site as remote images.
In some cases, it may in fact be possible. It is possible for the remote server to be configured to allow it. However this configuration would need to be done on the remote server, so if you don't have access to that then the problem remains.

Canvas cross-domain image data policy not working with my CMS (Cargo). Do I need a new host?

I have a portfolio on Cargo Collective .
I've been trying to implement a JS-driven dynamic header that uses canvas.
EXAMPLE HERE
I am drawing a PNG image on the canvas and capturing pixel information with getImageData().
Everything works fine when I test it locally, but once on Cargo I get the dreaded tainted canvas error:
Unable to get image data from canvas because the canvas has been tainted by cross-origin data.
Uncaught Error: SECURITY_ERR: DOM Exception 18
This stems from the fact that on the Cargo CMS images are hosted on their own servers on addresses such as: media.cargocollective.com/1/7/245266/headerimg/FlakeSixBlack.png
The only obvious solution I see to this is to buy some web space just to host this single image that I use programmatically. This sounds a bit stupid and partially defeats the purpose of relying on a third-party CMS.
Is there any other way to work around this?
If there isn't, how would I go about managing the DNS A records for two differents hosts?
My home page address http://flakesix.com would have to point to the Cargo Collective servers, while the image would have to be retrieved from another server (GoDaddy for example, which is where I got the domain name from).
I'm a little lost.
Any help appreciated.
If you already know what your image is, why not try and embed a base 64 conversion of it within your script ?
Here is some documentation/tool coming to Data Urls :
http://dataurl.net/#about

canvas.toDataURL Alternative?

I'm trying to convert an the contents of an HTML5 canvas to a png image.
Problem is that the canvas contains an image that isn't hosted locally so I get the security error.
I don't have the option to host the image locally, is there any other way to capture what is inside the canvas element?
Thanks!
Unless you can make your image resource CORS friendly, then no.
https://developer.mozilla.org/en-US/docs/CORS_Enabled_Image#What_is_a_.22tainted.22_canvas.3F
Although you can use images without CORS approval in your canvas,
doing so taints the canvas. Once a canvas has been tainted, you can no
longer pull data back out of the canvas. For example, you can no
longer use the canvas toBlob(), toDataURL(), or getImageData()
methods; doing so will throw a security error.
Edit: Of course, if you aren't limited to pure HTML5 methods, there are some Flash/Crossdomain.xml tricks you could use, but that still assumes you have some control over the server which serves the images.
If you're not opposed to using jQuery this plugin my do the trick.
http://www.maxnov.com/getimagedata/
Guess there is no way around that on the client-side otherwise what would be the point of blocking toDataURL anyway right?
Maybe you could have a server side script forwarding external images to the client so the browser won't know it's from another domain. (Not that it need to anyway since you can't use the browser's credentials from the server side)
Just send the image url as a get parameter, have the content-type header modified according to the image file, of course, and just spread all those bytes on the response content.

Is there a way to do client side image mashup in HTML 5 and javascript only

I'm working on an image mashup web app.
I want to avoid flash or other client hassles and just do it pure HTML+javascript.
To keep it light, I'd like to do the work on the client side in Javascript, and have it just push a final saved image to the server.
I thought after reading about the wonders of HTML5 and Canvas I'd be able to use that.
Trouble is though:
If I use the new drag and drop feature of HTML5 for the user to pass a local image to the app and then paint it to the canvas, then ... the canvas get's dirty and it throws a security exception if I try to save the image data.
If I use an API like Bing Image search to find images for the user and paint them to the canvas, then ... the canvas gets dirty and it throws a security exception if I try to save the image data.
The only work around I can think is to have the server act as a kind of proxy and have it relay every image that is worked with to the client - but that defeats the purpose of going client side.
Is there any other method I'm not thinking of, or is pure HTML5 + JS at the client side just not an option for this use case?
The security exception is thrown because you are using images from different domain (local or Bing in your case), you should give to the user the ability to upload the selected images on your server and then work with them in canvas. For images from internet storages you can make something like a proxy to show them on the frontend, images from user's pc should always be uploaded. There is no other way to avoid XSS exceptions as far as I know.
P.S. there is a good article about HTML5 canvas image restrictions here: http://simonsarris.com/blog/480-understanding-the-html5-canvas-image-security-rules

Categories

Resources