Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proxying of document.cookie

I need to log setting of document.cookie. I can not redefine cookie property just with document.cookie = {...} So I need to get setter for document.cookie. But Object.getOwnPropertyDescriptor(document, "cookie") returns undefined.

UPD. While I was writing the question I found a working solution, but it uses deprecated __lookupGetter__ and __lookupSetter__ methods. Is there any solution which doesn't use obsolete API?

like image 610
Vlad Shevchenko Avatar asked Sep 05 '15 06:09

Vlad Shevchenko


People also ask

What is the use of document cookie?

The Document property cookie lets you read and write cookies associated with the document. It serves as a getter and setter for the actual values of the cookies.

Where are document cookies stored?

Cookies are small strings of data that are stored directly in the browser. They are a part of the HTTP protocol, defined by the RFC 6265 specification. Cookies are usually set by a web-server using the response Set-Cookie HTTP-header.

Is document cookie a string?

The document.cookie property looks like a normal text string. But it is not. Even if you write a whole cookie string to document.cookie, when you read it out again, you can only see the name-value pair of it.

How do I retrieve data from cookies?

Read cookie using JavaScript: This function retrieves the cookie data stored in the browser. The cookie string is automatically encoded while sending it from the server to the browser. Hence it needs to be decoded before the actual data can be retrieved.


1 Answers

The standardized way of accessing getters and setters is with Object.getOwnPropertyDescriptor, but as the name suggests, it only looks on the objects own properties (it does not look up the prototype chain). document is an instance of HTMLDocument, which inherits from Document. In modern browsers the cookie property is defined on Document.prototype, whereas in older versions of Firefox it is defined on HTMLDocument.prototype.

var cookieDesc = Object.getOwnPropertyDescriptor(Document.prototype, 'cookie') ||
                 Object.getOwnPropertyDescriptor(HTMLDocument.prototype, 'cookie');
if (cookieDesc && cookieDesc.configurable) {
    Object.defineProperty(document, 'cookie', {
        get: function () {
            return cookieDesc.get.call(document);
        },
        set: function (val) {
            console.log(val);
            cookieDesc.set.call(document, val);
        }
    });
}

Ironically, in the most privacy-concerned browser Safari, the descriptor has set configurable to false and does not contain the getter nor setter, and neither does __lookupGetter__ or __lookupSetter__. So I haven't found a way to override document.cookie in Safari yet (8.0.8 on OS X and iOS 9.0.2). WebKit nightly acts the same way as Safari, so it doesn't seem to get fixed anytime soon.

Update October 2019: Tested the above code in Safari 12.1.2 on MacOS Mojave, and cookieDesk is now configurable! This means my proof of concept document.cookie protection from 2015 might actually work now :)

like image 61
gregers Avatar answered Sep 27 '22 16:09

gregers