Search code examples
javascriptgoogle-chrome-extensionchrome-extension-manifest-v3

How can one exclude requests with no initiator from declarativeNetRequest rules?


I'm creating declarativeNetRequest rules and I'm having trouble excluding requests with no initiator from those rules (using chrome version 112.0.5615.139 (Official Build) (64-bit)). An example use case is if a user manually enters a url directly into the address bar, the rules should not intercept the request.

I've tried excluding the following without success:

excludedInitiatorDomains: ["", "null", "newtab", "localhost", "about:blank", "chrome://"]

I know that chrome.runtime.id works for requests initiated by the extension, but I'm not sure how to exclude requests initiated by the user or browser. Any help with this would be greatly appreciated!

MCVE:

manifest.json:

{
  "name": "Chrome Extension Initiator Domain MCVE",
  "version": "1.0",
  "manifest_version": 3,
  "declarative_net_request": {
    "rule_resources": [
      {
        "id": "ruleset_1",
        "enabled": true,
        "path": "rules.json"
      }
    ]
  },
  "permissions": [
    "declarativeNetRequest",
    "declarativeNetRequestFeedback"
  ],
  "host_permissions": [
    "*://*.google.com/*"
  ],
  "background": {
    "service_worker": "background.js"
  }
}

rules.json

[
  {
    "id": 1,
    "action": { "type": "block" },
    "condition": {
      "urlFilter": "google.com",
      "resourceTypes": ["main_frame"],
      "excludedInitiatorDomains": ["google.com", "", "null", "newtab", "localhost", "about:blank", "chrome://"]
    }
  }
]

background.js

chrome.declarativeNetRequest.onRuleMatchedDebug.addListener(info =>
    console.log(info)
)

Here is what gets logged when opening a new tab and directly navigating to google.com:

{
    "request": {
        "documentLifecycle": "active",
        "frameId": 0,
        "frameType": "outermost_frame",
        "method": "GET",
        "parentFrameId": -1,
        "requestId": "72065",
        "tabId": 852200437,
        "type": "main_frame",
        "url": "https://www.google.com/"
    },
    "rule": {
        "ruleId": 1,
        "rulesetId": "ruleset_1"
    }
}

Solution

  • You only need to change rules.json

    • Instead of "excludedInitiatorDomains", use "initiatorDomains"
    • List all valid TLDs

    In the following example, I've only listed three common TLDs.
    But I've also tried it with a list of ~1400 TLDs (only the ASCII ones) and a few country-specific search engines as the initiators.
    There were no complaints from Chromium 112.0.5615.165 (Official Build) Arch Linux (64-Bit)

    Get the complete TLD list from IANA > Database of Top Level Domains > Hint and Zone Files > Top-Level Domains
    You must encode non-ASCII domains with Punycode, or Chrome will refuse to load the extension:
    chrome.declarativeNetRequest > RuleCondition > initiatorDomains

    This is probably the only way to accomplish what you want, unless you're willing to use "webRequestBlocking".

    rules.json

    [
        {
            "id": 1,
            "action": { "type": "block" },
            "condition": {
                "urlFilter": "google.com",
                "resourceTypes": ["main_frame"],
                "initiatorDomains": [
                    "com",
                    "net",
                    "org"
                ]
            }
        }
    ]