google-chrome-extensionchrome-extension-manifest-v3response-headers

Chrome declarativeNetRequest.updateDynamicRules - response headers modification breaks other not related webapps


I'm trying to add a response header to some requests using my chrome extension. While it works as expected for the website I'm trying to deal with, it breaks some other web applications not even specified in the manifest. I noticed, those apps are using SSO authentication and it breaks them while it loads the page.

One of the examples: During initial load a webapp (ASP.NET dashboard) is loading some resources (page itself, scripts, some json file) and then it's making an API call to https://dc.services.visualstudio.com/v2/track. I compared all calls up until this one - all look the same, and this is the first one that fails if I have my extension installed. If I remove the extension - everything works fine, app is loading and showing the dashboard. I also noticed that this API call is not exactly the same as the one from working scenario (without extension installed). It's missing a lot of headers (7 vs 21), and it's not even showing if it's a preflight or actual POST request.

I spent a lot of time trying to debug and see what's wrong, but no luck so far.

Here is my config

manifest.json

{
  ...
  "permissions": [
    "webRequest",
    "notifications",
    "storage",
    "tabs",
    "activeTab",
    "cookies",
    "scripting",
    "declarativeNetRequest"
  ],
  "host_permissions": [
    "*://somedomain.com/*"
  ],
  "background": {
    "service_worker": "background.js",
    "type": "module"
  }
}

background.js

...
chrome.declarativeNetRequest.updateDynamicRules({
  removeRuleIds: [123456],
  addRules: [{
    id: 123456,
    priority: 1,
    condition: {
      regexFilter: 'https://somedomain.com', // tried urlFilter too
      domains: ['somedomain.com'],
      resourceTypes: [
        chrome.declarativeNetRequest.ResourceType.MAIN_FRAME
      ]
    },
    action: {
      type: chrome.declarativeNetRequest.RuleActionType.MODIFY_HEADERS,
      responseHeaders: [
        {
          header: 'foo',
          operation: chrome.declarativeNetRequest.HeaderOperation.SET,
          value: 'bar'
        }
      ]
    }
  }]
})

As you see - I'm setting a custom header here (just for an example). Real intention is to modify Content-Security-Policy header. No matter what header I'm touching or adding - the result is always the same. If I provide an empty array in responseHeaders setting in background.js - everything works. It starts failing if there is an entry in that array.

chrome.declarativeNetRequest.getDynamicRules() returns only the rule I've created - no other rules.

I also tried to add a similar static rule to manifest.json. It gives the same result.

Any ideas would be much appreciated.


Solution

  • Thanks @wOxxOm for a right direction. This is indeed a bug in Chromium - https://bugs.chromium.org/p/chromium/issues/detail?id=1468558

    I've used one of the suggestions from the bug page and added a workaround to my code, which worked well.

    The workaround was to add a dummy listener to background.js:

    chrome.webRequest.onBeforeSendHeaders.addListener(
      () => {},
      { urls: ['<all_urls>'] },
      ['requestHeaders', 'extraHeaders'],
    );
    

    I also had to modify host_permissions in manifest.json like this:

    "host_permissions": ["<all_urls>"]