1

EDIT: After being recommended to work with headers, I asked a similar question here.

I'm trying to develop a Chrome extension that analyzes cookies being set/retrieved by websites and, if a cookie doesn't meet certain requirements, stops it from being set/retrieved.

I figured I would have to override the cookie setter and getter.

I have found similar questions:

Cookie Law, Cookie setter & getter

Safely overriding document.cookie in Google Chrome extension

Defining a getter for document.cookie

Retrieving document.cookie getter and setter

Reading the answers I have to say I am quite confused and am no longer sure what I'm trying to do is even possible.

Nevertheless, referring to question #3 in particular, I tried coming up with a simple test extension that overrides cookie getter and setter with functions that don't do anything (so no cookie should ever be set while this extension is active). These are the 3 files the extension is made of.

manifest.json

{
  "manifest_version": 2,

  "name": "Test",
  "description": "Test extension",
  "version": "1.0",

  "permissions": [
    "<all_urls>",
    "tabs",
    "webRequest",
    "webRequestBlocking"
  ],

  "background": {
    "scripts": ["background.js"]
  }
}

background.js

chrome.webRequest.onBeforeRequest.addListener(
  function(details) {
    chrome.tabs.executeScript(null, {
      file: "cookiescript.js"
    });
  }, {
    urls: [
      "<all_urls>"
    ]
  }, ["blocking"]);

cookiescript.js

var old_cookie = document.cookie;

Object.defineProperty(document, 'cookie', {
  get: function() {
    console.log('Getting cookie...');
    return '';
  },
  set: function(val) {
    console.log('Setting cookie...');
  }
});

document.cookie = old_cookie;

I usually test this on en.wikipedia.org as it sets various cookies the moment you visit it. However, with the above extension, the console log becomes filled with Getting cookie... alternated with Uncaught TypeError: Cannot redefine property: cookie, and when I check cookies stored, I can see that Wikipedia created all the cookies it wanted regardless of my extension.

The error seems to speak clear: you can't override cookie setter and getter, but the fact that other questions (#3 in particular) were answered saying to do just that, I am not sure.

Alternatively, I tried using this version of cookiescript.js, which adopts the (deprecated) defineSetter and defineGetter

var old_cookie = document.cookie;

document.__defineSetter__('cookie', function() {
  console.log('Setting cookie...');
});
document.__defineGetter__('cookie', function() {
  console.log('Getting cookie...');
  return ('');
});

document.cookie = old_cookie;

Console log results in an alternation of Setting cookie... and Getting cookie..., but again, looking at cookies saved, it looks like Wikipedia successfully set all of its cookies.

Would anyone be able to point out what I'd have to do to successfully be in-between cookie setting/getting so that I could stop it, or explain if what I'm trying to do is just impossible?

My wild guess would be that the overriding of getter/setter actually happens, but only after the website set/got its cookies, but I'd have no idea how to make sure my overriding happens first instead (I figured the use of blocking onBeforeRequest would've achieved that, but I seem to be wrong), or if it's simply impossible to do so.

EDIT: I previously mentioned how a different extension to list cookies would not be able to retrieve them, so I thought I successfully overrode the getter. I was mistaken, this extension was broken, and when fixed it was displaying all the cookies.

Community
  • 1
  • 1

1 Answers1

2

I think you're trying hard to reinvent the wheel here. Quoting the docs:

Use the chrome.cookies API to query and modify cookies, and to be notified when they change.

I get it that sometimes you want to prevent it in the first place, and let's take a look at that as well, but you've got to understand how cookies work. There are 2 kinds of cookie set operations:

  1. By the client, by document.cookie manipulation. Then your approach may help, but to ensure that the cookie is intercepted you cannot rely on programmatic injection, it is indeed too slow. You need to declare it in the manifest with a proper run_at parameter:

    "content_scripts" : [{
      "matches" : ["<all_urls>"],
      "js": ["cookiescript.js"],
      "run_at": "document_start"
    }]
    

    This will ensure your code executes before anything else on the page (before there is even anything in the DOM).

  2. By the server as part of the HTTP response. It may even be HTTP-Only cookie that's not exposed to document.cookie.

    You can intercept that as well, but you need to use webRequest for that, specifically a blocking response to onHeadersReceived can examine and modify headers that set cookies, and a blocking response to onBeforeSendHeaders can modify cookies reported to the server.

Xan
  • 74,770
  • 16
  • 179
  • 206
  • Point 1 didn't really change anything, my extensions can still set and read cookies, but stopping/filtering them is not my main goal, I'm more interested in the activity with the server. In point 2, are you saying I shouldn't worry about overriding setter/getter, but instead try to alter headers? – user3648026 Feb 12 '16 at 18:04
  • Tried _onHeadersReceived_ with options _blocking_ and _responseHeaders_. Similar to the example on the page you linked, I scan all header elements and splice _details.responseHeaders[i]_ whenever its name is equal to _Set-Cookie_. I thought it would prevent cookie setting entirely, but looking at cookies stored after visiting _en.wikipedia.org_, the only difference is, with addon, cookies appear for domains: _upload.wikimedia.org en.wikipedia.org_. Without addon, _wikipedia.org_ appears too, so only this one is blocked. Looks like working with headers won't solve it, or I'm missing something. – user3648026 Feb 12 '16 at 21:12
  • You are missing something. Maybe you're too liberal with URL filtering for webRequest. Remember that you need a permission for all URLs you're trying to catch as well. – Xan Feb 12 '16 at 21:13
  • I'm using _urls: [""]_ so that shouldn't be a problem. This is the background page. Manifest permissions are _, webRequest, webRequestBlocking, tabs_. `chrome.webRequest.onHeadersReceived.addListener( function(details) { for (var i=0;i< details.responseHeaders.length;i++) { if (details.responseHeaders[i].name === 'Set-Cookie') { details.responseHeaders.splice(i, 1); i--; } } return {responseHeaders: details.responseHeaders}; }, {urls: [""]}, ["blocking", "responseHeaders"]);` – user3648026 Feb 14 '16 at 17:07
  • Code in comments.. I'm not even going to read this. At this point, making a new question is the best course of action. – Xan Feb 14 '16 at 17:08
  • 1
    As suggested, I made a new question. If anyone is interested, it's [here](http://stackoverflow.com/questions/35395105/blocking-cookie-setting-retrieving-by-modifying-headers) – user3648026 Feb 14 '16 at 17:57