Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is canvas security model ignoring access-control-allow-origin headers?

It seems that even if you set the access-control-allow-origin header to allow access from mydomain.org to an image hosted on domain example.org, the canvas' origin-clean flag gets set to false, and trying to manipulate that image's pixel data will trigger a security exception.

Shouldn't canvas' obey the access-control-allow-origin header and allow access to image's data without throwing an exception?

like image 487
ArtBIT Avatar asked Jun 06 '10 17:06

ArtBIT


People also ask

How do I fix CORS policy no Access-Control allow origin?

If the server is under your control, add the origin of the requesting site to the set of domains permitted access by adding it to the Access-Control-Allow-Origin header's value. You can also configure a site to allow any site to access it by using the * wildcard. You should only use this for public APIs.

How do you allow cross-origin use of images and canvas?

The key is to use the crossorigin attribute by setting crossOrigin on the HTMLImageElement into which the image will be loaded. This tells the browser to request cross-origin access when trying to download the image data.

Why CORS is needed?

The CORS mechanism supports secure cross-origin requests and data transfers between browsers and servers. Modern browsers use CORS in APIs such as XMLHttpRequest or Fetch to mitigate the risks of cross-origin HTTP requests.


1 Answers

Actually, canvas DOES honour "access-control-allow-origin" if image has "crossOrigin" attribute with value "anonymous".

Works quite well in a fixed example: http://jsfiddle.net/WLTqG/29/

var ctx = document.getElementById('c').getContext('2d'),
    img = new Image();
img.crossOrigin = 'anonymous';
img.src = 'https://lh3.googleusercontent.com/-LAFgeyNL894/AAAAAAAAAAI/AAAAAAAAAAA/-CWBGs9xLXI/s96-c/photo.jpg';

img.onload = function() {
    ctx.drawImage(img, 0, 0);
    try {
        var imgData = ctx.getImageData(0, 0, 100, 100);
        $('.button').on('click', function(e) {
            e.preventDefault();
            applyFilter(ctx, imgData);
        });
    } catch(err) {
        $('.button').hide();
        $('body').append("Access denied");
        console.log(err);
    }
};
function applyFilter(ctx, data) {
    for (var x = 0; x < data.width; x++) {
        for (var y = 0; y < data.height; y++) {
            var index = 4 * (y * data.width + x);
            data.data[index] = data.data[index] - 50; //r
            data.data[index+1] = data.data[index+1] - 50; //g
            data.data[index+2] = data.data[index+2] - 50; //b
            data.data[index+3] = data.data[index+2] - 50; //a
        }
    }
    ctx.putImageData(data, 0, 0);
}

(I used jQuery only for DOM-manipulation and events handling)

like image 148
tibalt Avatar answered Sep 28 '22 19:09

tibalt