Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A javascript to selectively block cookie creation by other javascript on page

I've wrote this javascript which blocks the creation of cookies by all the others javascript on page (I have jquery on page too):

jQuery(document).ready(function () {
  Object.defineProperty(document, 'cookie', {
    get: function () {
        return '';
    },
    set: function (value) {
    }
  });
});

Now I need to go a step further. I need to selectively block cookies, something like this:

jQuery(document).ready(function () {
  Object.defineProperty(document, 'cookie', {
    get: function () {
        if (value == ...) {
          //call to "parent" function here  
        } else {
          return '';
        }
    },
    set: function (value) {
        if (value == ...) {
          //call to "parent" function here
          //document.cookie ???
        }         
    }
  });
});

Is it possible to call the "parent"/"native" function? I've tried with document.cookie but browser starts a loop, calling again my function (which is right).

Thanks in advance

Mariella

like image 554
Mariella Avatar asked Sep 12 '25 08:09

Mariella


1 Answers

You cannot do that while your getter/setter proxy is active.

The problem is that document.cookie does not use JavaScript getters and setters, but (presumeably) native ones, which we can't access.
You can see that by calling Object.getOwnPropertyDescriptor:

JSON.stringify(Object.getOwnPropertyDescriptor(document, 'cookie'));

(I can't make this a snippet because snippets cannot access cookies.)
In Chrome:

{
    "value": "...",
    "writable": true,
    "enumerable": true,
    "configurable": true
}

In Firefox:

undefined

And without getting a hold of the function that handles the assignment, you have no means of calling it.

However, if you delete document.cookie, Jon Skeet puts it it automagically reverts back to normal.

So what you can do is store the assignments somewhere, delete your proxy at some point (window.onunload ultimately) and reassign everything to document.cookie there, like

function getCookies()
{
    var cookies = {};
    var list = document.cookie.split(';');
    for(var i = 0; i < list.length; i++)
    {
        var split = list[i].split('=');
        cookies[split[0].trim()] = split[1];
    }
    return cookies;
}

function hijackCookies()
{
    var cookies = getCookies();
    Object.defineProperty(document, 'cookie',
    {
        configurable: true,
        enumerable: true,
        get: function()
        {
            var list = [];
            for(var key in cookies)
            {
                list.push(key + '=' + cookies[key]);
            }
            return list.join('; ');
        },
        set: function(value)
        {
            var split = value.split('=');
            var key = split[0].trim();
            if(/* YOUR FILTER HERE */)
            {
                return;
            }
            cookies[key] = split[1];
        }
    });
    return function()
    {
        delete document.cookie;
        for(var key in cookies)
        {
            document.cookie = key + '=' + cookies[key];
        }
    };
}

var detach = hijackCookies();

// Do something with cookies or let 3rd party code run
// ...

detach();

[ Fiddle ] (Note: Reloading the entire page and clicking "run" is not the same!)

Tested in Firefox 38.0.1 and Chrome 42.0.2311.152.

like image 193
Siguza Avatar answered Sep 13 '25 21:09

Siguza