Feedback from the ad blocking community on the proposed changes to the webRequest and declarativeNetRequest APIs

Last Updated: 02/08/2019

The Chromium team have proposed changes to key extension APIs, as well as the overall architecture of extensions in its manifest V3 update. They have released a public document outlining a high level overview of these changes.

The planned changes would restrict the webRequest API and they plan to add a new API called declarativeNetRequest. The following is our feedback on these proposed changes, which include our concerns and suggestions. 

Platform limitations with the new proposed changes in manifest V3 with respect to webRequest and declarativeNetRequest APIs

Based on the current implementation of the declarativeNetRequest API in Chrome Canary, API documentation, and the draft specification of manifest V3, we see the following limitations in the extensions platform and how it would negatively affect the functionality of ad blockers and other privacy improving extensions. We are listing out all major problems and use cases, and some of these might have the same (or similar) suggested improvement. 

Problem

Use case this affects

Suggestion

MAX_NUMBER_OF_RULES is too low

Working with EasyList, and other filter lists.  

The maximum number of rules is currently 30,000. This is not enough for EasyList, which translates to approximately 40,000 rules,  let alone multiple filter lists (EasyPrivacy, language specific lists, etc.). Some ad blockers use as high as 120,000 filters currently, with more being added continuously. Pretty much every ad blocker available uses EasyList, along with their own supplemental  lists (which might have as many blocking rules). Users simply won't be able to use these supplemental  lists alongside EasyList, so this issue is very important. Furthermore, while there is some research on redundant rules in Easylist - some ad blocker’s own internal research (for example, from AdGuard) points to redundancies, but not as high as claimed in the above linked paper. As such, this is an issue that needs to be addressed and improved upon by the Easylist community.

There is also a concern regarding ad servers, knowing there is a limit, would intentionally group up to revolving ad servers. For example, Look at popads - where to get around a filter rule, they register a new random domain and serve ads from there, until that is blocked via a new filter rule, and  keep on repeating this. It'd take a few more ad companies to just add more servers on a regular basis to get through this limit, especially if the limit is small.  

Increase the maximum number of rules to at least 300,000 filters. This is to keep in mind current filter capacity for most ad blocking extensions, as well as need to scale up in the future years and allow users to  combine supplemental filter lists without issue. Also please keep in mind that we are looking at this as a maximum limit, and are not looking to reach this number anytime soon.

No way to know which requests and ads are blocked

Showing users which ads are blocked.

It’s important to be able to display a detailed analysis of trackers/ads blocked on any page (potentially with tracker’s categories, etc.). Not having any feedback from the blocking engine would prevent this completely. We cannot overstate the importance of this functionality.

With the declarativeNetRequest API, there is no way for the extension to know which requests have been blocked, let alone by which rule. Thus the user will have no way of knowing if the ad blocking extension is working correctly.

The MyAdBlock image replacement feature for Adblock (replacing blocked and hidden ads with cat & dog images) relies on being able to determine which elements on a web page were blocked or hidden by AdBlock. With the proposed declarative web request API this feature would no longer work.

Filter rules telemetry - i.e, way to observe rules are they are applied and the request they were applied to.

Issues with  optimizing filter lists

Optimizing our filter lists to remove redundant rules.  

For this we need to observe which rules are applied and the request they are applied to.

Filter rules telemetry - i.e, way to observe rules are they are applied and the request they were applied to.

Issues with countering malware

The lack of telemetry is also an issue from a malware blocking perspective. For example, heuristics based on prevalence are an important part of MalwareBytes’  arsenal for blocking of malicious sites. But without telemetry, those approaches and techniques cannot be used as it is impossible to get a handle on false positives (FPs) and false negatives (FNs).

Filter rules telemetry - i.e, way to observe rules are they are applied and the request they were applied to.

No way to update rule_resources at runtime

Updating the filter list frequently.

Filter lists are updated frequently (daily or even hourly in the case of ABP filters list or the Acceptable Ads whitelist). Releasing a whole new extension version everytime the filer list needs to be updated isn’t feasible (download size/time, possible review). This is especially important to counter adblock circumvention since many of these circumvention providers react fast, and hence, ad blockers need to push updates very fast as well to counter them so that ads remain blocked.

Dynamic Rule Support.

This would provide a way for filter lists to be updated frequently (many times a day) without requiring a new extension update.

No way for custom defined filters

Custom (user defined) filters.

Every ad blocker has the possibility for users to specify custom filters at run time. It’s an important feature from the user standpoint for them to have a way to define and use their own custom filters, and also very important from a developer standpoint, so that they can quickly try out new filters without needing to reload the extension. Filter list authors (for example the volunteers who contribute to EasyList) also need this functionality to continue try out new filters before contributing to their filter lists.

Dynamic Rule Support.

This would provide a way for user defined custom request blocking filters without requiring the extension to be reloaded.

Sub-optimal filter list update situation

Use all filter lists in their most up to date version.

The proposed changes to webRequest/declarativeNetRequest only affect filters that block resources as such it would still be possible/necessary to update element hiding filters separately. This would result in two different filter list update mechanisms, one for blocking filters and another for element hiding ones.This might even incentivise the use of element hiding over request blocking, despite that being suboptimal. Using such filters over their resource blocking counterpart can negatively impact performance, memory and bandwidth usage.

Dynamic Rule Support.

This would provide a way for filter lists to be updated frequently (many times a day) without requiring a new extension update.

Granular modification of requests (query parameters, cookies, etc.) would no longer be possible.

To remove unsafe data-points from requests before they leave the browser (fingerprints, cookies, etc.).

Cliqz’ Anti-tracking extensions rely on the possibility to not block all requests, but instead remove unsafe elements from them before they leave the browser (fingerprints, cookies containing a unique identifier, query parameter which contains a value that could be used to track a user, etc.). This finer grain blocking allows to increase the coverage of the protection while limiting breakage.

AdGuard also relies on this and instead of blocking it might modify or remove cookies, remove tracking parameters from request URLs, etc.

Allow the new APIs to preserve this functionality.

There should be a way to have this functionality in some way with the declarativeNetRequest API or some other way in manifest v3.

Upgrading unsafe HTTP requests to HTTPS would be negatively affected

Upgrading some HTTP requests to HTTPs automatically.

Having the possibility to upgrade unsafe HTTP traffic to HTTPs on the fly is important for some extensions like ‘HTTPS everywhere’ which help users be safe online. This doesn’t seem to be possible with the current proposed plan in V3.

Allow the new APIs to preserve this functionality.

There should be a way to have this functionality in some way with the declarativeNetRequest API or some other way in manifest v3.

Limited rule capabilities

Based on the current implementation of declarativeNetRequest in the latest Chrome Beta (as of version 72.0.3626.81), we have observed the following limitations. Below is a list of the capabilities which are lacking in declarativeNetRequest, the use case along with suggestions on how to address these limitations to strengthen the API with regards to the current capabilities of modern ad blockers. 

Capability

Use case description

Suggestion

Matching URLs by Regular Expression

Some ads cannot be targeted with simple glob patterns. Regular expression matching is important in these cases.

An option like condition.urlFilterIsRegExp for cases like that. It might even be OK if the number of regular expression rules are limited.

Recursive whitelisting (i.e. $document exception rules)

Adblock Plus, AdGuard and some other ad blocking extensions, support $document exception rules (used in EasyList), which essentially prevent anything from being blocked within a matching document (top-level or iframe) and recursively within any sub-document. This is somewhat similar to using addAllowedPages(), but the pattern accepted by addAllowedPages() is more limited, and it is only applied to top-level documents.

It would be great if there would be an “allow-sub-resources” action that, instead of whitelisting the matching request, whitelists everything within the document loaded by that request, just like $document exception rules.

Whitelisting all generic filters (i.e. filters without domain restriction) on selected URLs (i.e. $genericblock exception rules)

There is also the $genericblock filter option, which follows the same semantics as the $document filter option (see above), but instead of whitelisting everything within the document, it only prevents filters without domain restriction from blocking requests. That is useful when generic filters (i.e. filters without a domain restriction) cause false positives or other side effects on a page.

In order to support the $genericblock filter option properly, we need rule priorities (currently the priority seems to be ignored by block/allow rules), in addition to the aforementioned “allow-sub-resources” action.

$csp filters

There is the $csp filter option (used in EasyList) that injects a Content-Security-Policy header into the response of matching requests. This is very helpful in cases where websites go to quite some length trying to circumvent ad blocking (through service workers, inline scripts, plugins, etc.).

Provide a similar capability as the Content-Security-Policy header, to allow extensions to entirely block, or restrict by origin things like web workers, scripts and frames. For some websites “block all third party scripts” or “disallow all frames” is a necessary approach.

$redirect and $rewrite filters

These are important filters used by Adblock Plus, uBlock Origin and others.

For more detailed use cases, please see this issue on the Adblock Plus issue tracker or this one on the uBlock origin wiki.

Though the declarativeNetRequest API already has basic support for request redirection, there are some limitations making the functionality unworkable.

1. “Allow” rules must be able to override redirection rules.

2. Relative URLs for redirections need to be supported.

3. Some way to dynamically decide the redirection URL based on the original URL would be very useful.

In condition.urlFilter, the ^ character should match the end of the URL as well.

For the time being, we can add another rule using | instead, for each rule ending with ^, in order to get the correct behavior, but that would significantly increase the number of resulting rules which is already extremely limited

This seems to be a bug. Would be great to have it be fixed. Please See https://bugs.chromium.org/p/chromium/issues/detail?id=932086

$sitekey filters

The $sitekey mechanism allows to apply filters on a very large amount of domains without adding a separate filter for each domain.

Preserve this functionality.

Rules priority

AdGuard, Cliqz, Ghostery and uBlock Origin support the $important modifier which gives filters maintainers an option to make blocking rules prevail over “allow” rules in certain cases.

For instance, some filter lists might want to apply stricter rules than what EasyList does. Here’s a simple example: google analytics might sometimes unblocked by EasyList or EasyPrivacy in order to not break a website, and other filter lists can do nothing with it.

Let “priority” property control what exactly will happen to the request, not just use it for redirect rules exclusively.

Blocking popups / popunders

AdGuard, uBO, and Adblock Plus support a special $popup modifier. If it is specified, we prevent opening a new tab. There is no such option in the new API.

Either a new action type or let “action”: “block” close tab if it’s applied to the “main_frame”.

Redirect resources dictionary

Redirecting to “data:” URLs is used by AdGuard and uBO in certain cases. For instance, to redirect request to an empty 1x1 png. The new API supports this, but the rules file might become too huge if we will simply specify the full “data:” URL for every rule for which we need it.

Let us specify a dictionary for named redirect URLs so that instead of specifying the full “redirectUrl” we could simply use the resource name.

Origin URL condition

The new API allows using “domains” for matching request origin. This is sometimes not enough, especially when there is a huge portal websites with different web apps in different locations of it (for instance, example.com/maps, example.com/news, etc).

Add originUrlFiltercondition.

Going beyond current use cases

Above we have talked about our current use cases, and how the proposed implementation in manifest V3 regarding webRequest and declarativeNetRequest could cause serious issues to them. However, another important thing to consider is future use cases.

Specific, precise use-cases are fine, but they are only driven by what is possible today. The flexibility of extensions for years have allowed developers, companies, individuals, to innovate continuously to protect privacy better and better. Ad blockers as we know them today probably would not even exist if we never had any browser extension APIs allowing their conception; maybe we would never have shed light on the tracking ecosystem on the internet if we would not have had the possibility to monitor their requests from extensions.

Flexible browser extension APIs allow innovation. We will never know how many new methods, that could be invented tomorrow, we are preventing by constraining the APIs today. People are continuously improving, fine-tuning, creating new ways to prevent tracking, fingerprinting, etc. because it's easy to write an extension in JavaScript and get started.

One major area where this could be especially problematic in the ad blocking space is ad blocking circumvention (the practice of getting around the ad blocker to force annoying ads on users who have an ad blocker installed). This is a space where things move very fast, and both sides are heavily investing time and effort to get ahead in this cat-and-mouse game. The proposed changes (if implemented as they exist currently) could seriously affect the ability for ad blockers to counter ad blocking circumvention.

If the new APIs are still undergoing design changes and improvements, then we would like it to allow for flexibility and freedom for extension authors to implement their own fine grained approaches towards ad blocking and anti-tracking in order to best tackle challenges in this fast moving field. We would like the declarativeNetRequest API to reach a mature state before the blocking portion of webRequest is removed. Another possible approach could be to incentivize developers to use declarativeNetRequest for better performance for most of the heavy lifting, while still keeping the blocking portion of the webRequest API (perhaps in a rate-limited fashion) to deal with fine-tuning, extra privacy protection and any other edge cases.

Conclusion

For the sake of not just the present, but also the healthy and open web ecosystem of the future, we need to make sure that we allow APIs that continue to foster innovation. Our very serious concern is that the proposed changes in manifest V3, especially with the proposed changes to webRequest and the current implementation of declarativeNetRequest might very well do the opposite. 

However, we still do welcome efforts to improve upon security, privacy and performance. If the changes we mentioned in this document are implemented, it could pave the way for more performant ad blocking without sacrificing the important core functionality of modern ad blocking extensions as they exist currently. Most modern ad blockers are already quite efficient and are constantly looking to improve performance further. We would encourage the Chromium team to feel free to engage more with the ad blocking developer community regarding manifest V3. We would be happy to provide more technical feedback, suggestions and support. 

Document contributors / supporters

(in alphabetical order)

  • Ad Remover
  • Adblock
  • Adblock Plus
  • AdGuard
  • Avira
  • Cliqz / Ghostery
  • Fanboy (Easylist author)
  • MalwareBytes
  • MonztA (Easylist author)