Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inconsistency: declarativeNetRequest rules able to block background requests from other extensions #369

Closed
sammacbeth opened this issue Mar 22, 2023 · 8 comments
Labels
implemented: chrome Implemented in Chrome implemented: firefox Implemented in Firefox implemented: safari Implemented in Safari topic: dnr Related to declarativeNetRequest

Comments

@sammacbeth
Copy link

Extensions' declarativeNetRequest rules are able to block requests initiated by other extensions. This is a change from MV2, where chrome.webRequest had no visibility of these requests.

Example

An extension defines the following rule, with the intent of blocking requests to example.com on pages loaded in the browser:

{
    "id": 1,
    "priority": 1,
    "action": {
      "type": "block"
    },
    "condition": {
      "requestDomains": ["example.com"],
      "resourceTypes": [
        "csp_report",
        "font",
        "image",
        "main_frame",
        "media",
        "object",
        "other",
        "ping",
        "script",
        "stylesheet",
        "sub_frame",
        "webbundle",
        "websocket",
        "webtransport",
        "xmlhttprequest"
      ]
    }
  }

Should another extension how wish to make a request to example.com from their background script/service worker, it will be blocked:

fetch('https://example.com/') // blocked

Current browser status

I tested this in Chrome, Firefox and Safari using these test extensions. Steps to reproduce:

  1. Download the attached zip and extract somewhere.
  2. Install the extracted "extension-requests" subdirectory as an unpacked extension.
  3. Open the background console for the extension requests demo extension.
  4. Switch to the network panel, and see the requests to https://testpages.kzar.co.uk/ being made every second successfully.
  5. Install the "extension-request-blocking-mv3" subdirectory as an unpacked extension.

(For Firefox and Safari minor changes are needed for the extensions to load).
Results:

Discussion

We came across this issue due to a user reported issue on our extension repo (duckduckgo/duckduckgo-privacy-extension#1732). A youtube.com block rule was preventing the FeedBro extension from fetching RSS feeds from their background page. This was unexpected for us, as these requests are not visible in chrome.webRequest.

The issue can be mitigated by using a excludedTabIds: [-1] condition, however this also prevents the rule from matching requests initiated by website service workers (which is important for tracker blockers).

I believe this issue will introduce significant unexpected extension breakage, plus introduce new ways for extensions to sabotage each other. For example, an extension could prevent a privacy extension from fetching updates to their blocklist rules.

@erosman
Copy link

erosman commented Mar 22, 2023

For example, an extension could prevent a privacy extension from fetching updates to their blocklist rules.

The opposite is also worth considering.
A privacy extension settings rules but other extensions bypassing those rules, thus relaxing the privacy aspect.

@Rob--W Rob--W added implemented: safari Implemented in Safari supportive: chrome Supportive from Chrome supportive: firefox Supportive from Firefox topic: dnr Related to declarativeNetRequest and removed needs-triage labels Mar 30, 2023
@Rob--W
Copy link
Member

Rob--W commented Mar 30, 2023

This topic was already discussed at the previous meeting (PR with meeting notes: #363), with vendor-specific issues tracked at https://crbug.com/1421697 (Chrome) and https://bugzil.la/1810753 (Firefox). The consensus is to not let extensions affect requests from other extensions.

For reference, the notes from two weeks ago are:

DNR blocking requests from other extensions
* [rob] (forked off previous discussion) Unlike Chrome, Firefox won't allow extensions to block other extensions' requests (https://bugzilla.mozilla.org/show_bug.cgi?id=1810753).
* [sam] At DuckDuckGo we had user feedback that we were blocking requests made by another extension; https://bugs.chromium.org/p/chromium/issues/detail?id=1421697
* [rob] Oliver, would you consider this a bug?
* [oliver] My first inclination is that this is a bug, since we have a flag to explicitly allow extensions to run scripts and access other extensions.
* [rob] Timothy, what's Safari's behavior?
* [timothy] I don't know offhand.
* [rob] What would the desired behavior be? E.g. background script sends a request to a remote destination.
* [timothy] I don't think that we would/should apply DNR rules in other extensions. Background script request is safe; request in content scripts may not be.
* [rob] In Firefox background script fetches cannot be intercepted/blocked by other extensions, but requests from content scripts can.
* [simeon] How about sandboxed extension pages?
* [rob] That's a good one…

The above position was repeated in today's meeting notes (pending review to be merged at #371).

@erosman
Copy link

erosman commented May 21, 2023

There are a number of areas for consideration.

Rule Contexts

  • All
    All requests
    e.g. for a privacy extension

  • Self
    Requests originated from extension itself only
    e.g. adding/modifying own fetch/XmlHttpRequest headers

  • Browser
    Requests not-originated from an extension
    e.g. not interfering with another extension

  • Other ? (can be merged with browser context)
    Requests originated from other extensions

For example, condition.initiatorDomains may include a keyword to apply context e.g. all, browser, self, other.

Problem Areas

  • Privacy extension setting rules but another extension bypassing them
  • One extension interfering with another extension's legitimate operation
  • Extension interfering with browser's operation

@Dalzhim
Copy link

Dalzhim commented Feb 13, 2024

@erosman : Rule contexts are important for me and they're also an area where there's a lot of inconsistency right now. Here's what I have observed when trying to use declarativeNetRequest to provide credentials for matching requests.

                                     Firefox  Chrome  Safari
Content script fetch                 ✅       ✅      ✅
Content script WebSocket             ✅       ✅      ✅
Background service worker fetch      ✅       ✅      ❌ 
Background service worker WebSocket  ✅       ❌      ❌ 

These results are produced with this dynamic rule:

function getExtensionDomain()
{
	return new URL(chrome.runtime.getURL("")).hostname;
}

function startModifyingBackgroundRequests(token)
{
	return chrome.declarativeNetRequest.updateDynamicRules({
		removeRuleIds: [12354],
		addRules: [
			{
				"id": 12354,
				"priority": 1,
				"condition": {
					"initiatorDomains": [getExtensionDomain()],
					"requestDomains": ["example.com"],
					"resourceTypes": ["websocket", "xmlhttprequest"]
				},
				"action": {
					"type": "modifyHeaders",
					"requestHeaders": [
						{
							"operation": "set",
							"header":"Cookie",
							"value": ("__Secure-token=" + token)
						},
						{
							"operation": "set",
							"header":"Authorization",
							"value": ("Bearer " + token)
						}
					]
				}
			}
		]
	});
}

I would expect to be able to modify headers of my own extension in the background service worker on all browsers, but unfortunately it doesn't seem possible right now, and it's not clear whether these inconsistencies are being tracked.

@smalluban
Copy link

At Ghostery, we have a similar issue with the problem (mentioned above).

One of our users reported a broken page of another extension, which was blocked by our DNR rules. Everything except the DNR rules does not work (the extension does not receive any events from other extension pages, etc). Also, It is not possible to add a general allow rule to let requests get through.

As the extensions do not have access to each other, DNR rules should not run for the chrome-extension:// protocols.

@kzar
Copy link

kzar commented Jun 25, 2024

For folks following along here, we merged a fix for this in Chromium last night.

@Lovesbarber100

This comment has been minimized.

@Rob--W Rob--W added implemented: chrome Implemented in Chrome implemented: firefox Implemented in Firefox and removed supportive: chrome Supportive from Chrome supportive: firefox Supportive from Firefox labels Sep 24, 2024
@Rob--W
Copy link
Member

Rob--W commented Sep 24, 2024

I have added "implemented: chrome" because the behavior was changed in #369 (comment)

I am also changing "supportive: firefox" to "implemented: firefox", since Firefox has restricted extensions from affecting other extensions from the very beginning.

@Rob--W Rob--W closed this as completed Sep 24, 2024
kzar added a commit to kzar/duckduckgo-privacy-extension that referenced this issue Oct 30, 2024
A bug in the chrome.declarativeNetRequest API[1] meant that extensions could
block requests initiated by other extensions. This cross-extension request
blocking wasn't supposed to be possible[2], and led to lots of issues for users
with multiple browser extensions installed (for example, see this Privacy Badger
bug report[3]).

These cross-extension requests weren't associated with a tabId, and so could not
be differentiated from other such requests - including ServiceWorker initiated
requests. As a workaround, to avoid breaking the other extensions our users
might have installed, we stopped blocking any requests with no associated tabId.

Since then, we have fixed the bug in Chrome[4], and that fix was release with
Chrome 128. So let's re-enable ServiceWorker initiated request blocking again
and increase the minimum supported Chrome version to 128.

1 - https://crbug.com/40896400
2 - w3c/webextensions#369
3 - EFForg/privacybadger#2968
4 - https://chromiumdash.appspot.com/commit/486d638e6977dad73bd207dc914df9319afac152
kzar added a commit to kzar/duckduckgo-privacy-extension that referenced this issue Oct 30, 2024
A bug in the chrome.declarativeNetRequest API[1] meant that extensions could
block requests initiated by other extensions. This cross-extension request
blocking wasn't supposed to be possible[2], and led to lots of issues for users
with multiple browser extensions installed (for example, see this Privacy Badger
bug report[3]).

These cross-extension requests weren't associated with a tabId, and so could not
be differentiated from other such requests - including ServiceWorker initiated
requests. As a workaround, to avoid breaking the other extensions our users
might have installed, we stopped blocking any requests with no associated tabId.

Since then, we have fixed the bug in Chrome[4], and that fix was release with
Chrome 128. So let's re-enable ServiceWorker initiated request blocking again
and increase the minimum supported Chrome version to 128.

1 - https://crbug.com/40896400
2 - w3c/webextensions#369
3 - EFForg/privacybadger#2968
4 - https://chromiumdash.appspot.com/commit/486d638e6977dad73bd207dc914df9319afac152
kzar added a commit to kzar/duckduckgo-privacy-extension that referenced this issue Oct 30, 2024
A bug in the chrome.declarativeNetRequest API[1] meant that extensions could
block requests initiated by other extensions. This cross-extension request
blocking wasn't supposed to be possible[2], and led to lots of issues for users
with multiple browser extensions installed (for example, see this Privacy Badger
bug report[3]).

These cross-extension requests weren't associated with a tabId, and so could not
be differentiated from other such requests - including ServiceWorker initiated
requests. As a workaround, to avoid breaking the other extensions our users
might have installed, we stopped blocking any requests with no associated tabId.

Since then, we have fixed the bug in Chrome[4], and that fix was release with
Chrome 128. So let's increase the minimum supported Chrome version to 128, so
that we can re-enable ServiceWorker initiated request blocking in the future.

1 - https://crbug.com/40896400
2 - w3c/webextensions#369
3 - EFForg/privacybadger#2968
4 - https://chromiumdash.appspot.com/commit/486d638e6977dad73bd207dc914df9319afac152
kzar added a commit to duckduckgo/duckduckgo-privacy-extension that referenced this issue Oct 31, 2024
A bug in the chrome.declarativeNetRequest API[1] meant that extensions could
block requests initiated by other extensions. This cross-extension request
blocking wasn't supposed to be possible[2], and led to lots of issues for users
with multiple browser extensions installed (for example, see this Privacy Badger
bug report[3]).

These cross-extension requests weren't associated with a tabId, and so could not
be differentiated from other such requests - including ServiceWorker initiated
requests. As a workaround, to avoid breaking the other extensions our users
might have installed, we stopped blocking any requests with no associated tabId.

Since then, we have fixed the bug in Chrome[4], and that fix was release with
Chrome 128. So let's increase the minimum supported Chrome version to 128, so
that we can re-enable ServiceWorker initiated request blocking in the future.

1 - https://crbug.com/40896400
2 - w3c/webextensions#369
3 - EFForg/privacybadger#2968
4 - https://chromiumdash.appspot.com/commit/486d638e6977dad73bd207dc914df9319afac152
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
implemented: chrome Implemented in Chrome implemented: firefox Implemented in Firefox implemented: safari Implemented in Safari topic: dnr Related to declarativeNetRequest
Projects
None yet
Development

No branches or pull requests

8 participants
@kzar @sammacbeth @Rob--W @smalluban @erosman @Dalzhim @Lovesbarber100 and others