Airgap.js Cookie Regulation

In its capacity as a cookie regulation engine, airgap.js performs a few main functions. During initialization, it clears out unauthorized cookies. Additionally, due to how airgap.js interfaces with your web app, it has the benefit of regulating cookies before they can be set, whenever a script may try to set them. As a client-side CMP, there are some drawbacks. Any regulation that airgap.js implements needs to be practical from within an unprivileged client-side context. Cookies, as a technology, can have different quirks and configurations that lead to regulation being either impractical or impossible for client-side CMPs to regulate. This document serves to qualify some of the strengths and weaknesses of client-side cookie regulation, as well as lays out some key concepts to be aware of when asking yourself if a given cookie can or cannot be regulated.

Cookies set using JavaScript in a realm that airgap.js has been initialized in are possible for airgap.js to regulate. Reactive regulation is also possible, but off by default, for cookies set without using JavaScript (HTTP headers, etc.) or from a separate same-origin cross-realm context (extensions, etc.) using the data-cookie-listener-regulation="on" load option. Note that the end user's browser must support the CookieStore API to use reactive cookie regulation.

In our overview above, we mentioned that it is impractical and sometimes impossible to regulate certain types of cookies. This is a technical limitation across all client-side CMPs. Taking a step back:

  • Client-side web CMPs are implemented using JavaScript code running on a website.
  • Client-side JavaScript code cannot “see” or “modify” certain types of cookies
  • Therefore, client-side web CMPs cannot see or modify certain types of cookies

Due to airgap.js running within an unprivileged client-side context, it will only be able to extend its regulation ability to the interfaces that it is able to access. There are a few main limitations that impede client-side web CMPs from regulating cookies:

Cookies can be set with the HttpOnly property, which makes it so that client-side JavaScript can not access or mutate that cookie. HttpOnly cookies will only be sent in the Cookie HTTP request header to the relevant websites matching its domain attribute. Because of this, the majority of HttpOnly cookies cannot be regulated from the client-side. If airgap.js is able to intercept the setting of an HttpOnly cookie, we can regulate through prevention of the request, and sometimes can allow the request with cookies omitted, but will otherwise be unable to detect or regulate the cookie in question.

In browsers configured to allow third-party cookies, first-party JavaScript access to third-party cookies is blocked to prevent certain types of cross-site tracking. This means that airgap.js and other JavaScript CMPs are unable to detect or regulate third-party cookies.

If airgap.js is not initialized within a realm, it will not be able to directly regulate cookies set within that realm. Same-origin realm protection capacities allow airgap.js to initialize protections within some iframes and directly regulate the cookies set within them. Reactive regulation is also possible using the data-cookie-listener-regulation="on" data attribute in the top realm.

This is a cookie with a domain that matches the current page URL’s domain or parents. e.g. if a user is on test.example.com, a cookie is first-party if it’s set with either .test.example.com or .example.com in the cookie domain attribute. If a user is on example.com, they no longer match .test.example.com but still match .example.com

These are cookies that are not first-party, i.e. the domain attribute does not match the current page URL’s domain or parents. If a user is on example.com and something attempts to set a cookie for something.com, that cookie would be considered third-party and cannot be set by first-party client-side JavaScript. If a user is on test.example.com and something attempts to set a cookie for example.com, that cookie would be considered first-party because, while it isn't same-origin, it is an ancestor domain. The only way a third party cookie can be set is if it’s server-originated, and even then that network request can only set a cookie that is a first party cookie for that request location. For example, if I’m on example.com and send a network request to test.something.com, that network request can set a cookie for .test.something.com or .something.com, even though my origin is example.com.

Cookies set through client-side JavaScript within the context document itself, either by the customer’s code or third-party scripts they have included on the page. In code, this can look like document.cookie = 'cookie_name=cookie_value' or cookieStore.set('cookie_name', 'cookie_value')

Server-originated cookies are set from an HTTP response sent from a server. This is set through an HTTP response’s Set-Cookie header field). These tend to be more problematic for client-side CMPs to regulate due to being undetectable by client-side JavaScript code.

This is a property some cookies may have. The HttpOnly value of a cookie can be checked using the cookie view within the storage tab in browser Dev Tools. Once a cookie has been set with the HttpOnly attribute, that cookie is no longer accessible from JavaScript.