Why does canvas.toDataURL() throw a security exception?
Solution 1
In the specs it says:
Whenever the toDataURL() method of a canvas element whose origin-clean flag is set to false is called, the method must raise a SECURITY_ERR exception.
If the image is coming from another server I don't think you can use toDataURL()
Solution 2
Setting cross origin attribute on the image objects worked for me (i was using fabricjs)
var c = document.createElement("img");
c.onload=function(){
// add the image to canvas or whatnot
c=c.onload=null
};
c.setAttribute('crossOrigin','anonymous');
c.src='http://google.com/cat.png';
For those using fabricjs, here's how to patch Image.fromUrl
// patch fabric for cross domain image jazz
fabric.Image.fromURL=function(d,f,e){
var c=fabric.document.createElement("img");
c.onload=function(){
if(f){f(new fabric.Image(c,e))}
c=c.onload=null
};
c.setAttribute('crossOrigin','anonymous');
c.src=d;
};
Solution 3
If the image is hosted on a host that sets either of Access-Control-Allow-Origin or Access-Control-Allow-Credentials, you can use Cross Origin Resource Sharing (CORS). See here (the crossorigin attribute) for more details.
Your other option is for your server to have an endpoint that fetches and serves an image. (eg. http://your_host/endpoint?url=URL) The downside of that approach being latency and theoretically unnecessary fetching.
If there are more alternate solutions, I'd be interested in hearing about them.
Solution 4
Seems there is a way to prevent that if image hosting able to provide the following HTTP headers for the image resources and browser supports CORS:
access-control-allow-origin: * access-control-allow-credentials: true
It is stated here: http://www.w3.org/TR/cors/#use-cases
Solution 5
Finally i found the solution. Just need add the crossOrigin
as third param in fromURL
func
fabric.Image.fromURL(imageUrl, function (image) {
//your logic
}, { crossOrigin: "Anonymous" });
pop850
Updated on February 03, 2020Comments
-
pop850 over 4 years
Did I not get enough sleep or what? This following code
var frame=document.getElementById("viewer"); frame.width=100; frame.height=100; var ctx=frame.getContext("2d"); var img=new Image(); img.src="http://www.ansearch.com/images/interface/item/small/image.png" img.onload=function() { // draw image ctx.drawImage(img, 0, 0) // Here's where the error happens: window.open(frame.toDataURL("image/png")); }
is throwing this error:
SECURITY_ERR: DOM Exception 18
There's no way this shouldn't work! Can anyone explain this, please?
-
pop850 about 14 yearsthanks so much! like Mike R. I can't imagine how this could be security-related! :)
-
AlfonsoML about 14 yearsIf an attacker is able to guess the name of a picture that you have in a private site, he would be able to get a copy of it by painting in on a canvas and sending the new image to his site. The main restriction from my point of view is to avoid drawing the contents of another site, but security is too complex as the attacker can find a hole in any unexpected site.
-
Sam Dutton almost 14 yearsNote that the subdomain matters as well. In my experience, in Chrome at least, a SECURITY_ERR: DOM Exception 18 is raised when making a call that is perceived to be across subdomains: 1. in example.com/some/path/index.html for a video or image in foo.example.com 2. when going to the same page as in 1 but by entering the URL example.com/some/path/index.html and then attempting to call toDataUrl() for a video or image in www.example.com
-
kilianc over 12 years@AlfonsoML, maybe I'm wrong, but "If an attacker is able to guess the name of a picture that you have in a private site" probably he will grab the image with a curl non with a browser. My point of view: Public URL Public Content.
-
Sujay almost 12 years@pop850 I'm facing this issue even when I use a data URL. Is there a way that I can workaround this for data URLs?
-
skrat almost 12 yearsHi, I did just that, I have Access-Control-Allow-Origin: * on the images, I have crossorigin='anonymous', then I paint the image on canvas, then I call toDataUrl and I'm still getting the SECURITY_ERR: DOM Exception 18
-
Silver Gonzales almost 11 yearsaccess-control-allow-credentials: true will not work with access-control-allow-origin: *. When the former is set, the latter should have an origin value, not a wildcard value from developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS
-
chinna_82 almost 11 years@Bob let say i have a canvas to hold my clipboard image. Are you saying that i cant use toDataURL()? Please advice.
-
apsillers almost 11 years@kilianc This restriction exists to prevent an attacker from causing your browser (with authentication cookies) to fetch an image and send its contents to an attacker; the attacker doesn't have your cookies, so he can't use curl to get the same resources you are authorized to get. "Public URL, Public Content" is a rather flawed way of thinking: my Facebook page has public facing components, but there is much that is only accessible with the right authentication token.
-
Philip007 over 10 yearsThanks, it works for me in Chrome. I am not using fabric.js though
-
HOY about 7 yearsI do use fabricjs but could not solve it. How would you do this with this code? function wtd_load_bg_image( img_url ) { if( img_url ) { var bg_img = new Image(); bg_img.onload = function() { canvasObj.setBackgroundImage(bg_img.src, canvasObj.renderAll.bind(canvasObj), { originX: 'left', originY: 'top', left: 0, top: 0 }); }; bg_img.src = img_url; } }
-
vanowm over 6 yearsWorks in Firefox as well.
-
metamagikum over 4 yearsThis is the reason bur where is the soloution?