Modifying response headers in Chrome extensions

Viewed 3858

I'm trying to modify the referer-policy header with my Chrome extension, but it doesn't affect the response headers.

Manifest.json:

{
  "name": "My Example Extension",
  "version": "1.0",
  "description": "",
  "permissions": [
    "webRequest",
    "webRequestBlocking",
    "*://*/*"
  ],
  "background": {
    "scripts": ["background.js"],
    "persistent": true
  },
  "manifest_version": 2
}

background.js:

chrome.webRequest.onHeadersReceived.addListener(details => {
    let header = details.responseHeaders.find(e => e.name.toLowerCase() === 'referrer-policy');

    // Check if the header has been defined already
    if (typeof header !== 'undefined') {
        console.log ('Modifying header');
        header.value = 'strict-origin';
    }
    else {
        details.responseHeaders.push({ name: 'referrer-policy', value: 'strict-origin' });
    }

    return {responseHeaders: details.responseHeaders};
}, {urls: ["*://*/*"]}, ['blocking', 'responseHeaders']);

I added debug outputs which show that the code modifies or adds the header accordingly but there is no effect in the browser itself.

2 Answers

I was writing exactly the same code when trying to modify response headers in extension.

// manifest.json

  "permissions": [
    "webRequest", "webRequestBlocking", "https://developer.chrome.com/*"
  ]

// background.js

chrome.webRequest.onHeadersReceived.addListener(
  function(details) {
    const newHeader = {name:"foo", value:"bar"};
    const responseHeaders = details.responseHeaders.concat(newHeader);
    return { responseHeaders };
  },
  // filters
  {
    urls: ["https://developer.chrome.com/*"],
  },
  // extraInfoSpec
  ["blocking","responseHeaders"]
);

It just doesn't work at all.

Until I've changed the last argument to:

  // extraInfoSpec
  ["blocking","responseHeaders", "extraHeaders"]

It finally works.

By revisiting the document, in the last paragraphs of Life cycle of requests section:

Starting from Chrome 79, ... On the other hand, response header modifications do not work to deceive CORS checks. If you need to deceive the CORS protocol, you also need to specify 'extraHeaders' for the response modifications.

You were not returning the modified headers. Try with:

chrome.webRequest.onHeadersReceived.addListener(details => {
    let myResponseHeaders = details.responseHeaders;
    let header = myResponseHeaders.find(e => e.name == 'Referrer-Policy');

    // Check if the header has been defined already
    if (header) {
        console.log ('Modifying header');
        let headerIndex = myResponseHeaders.indexOf(header);
        myResponseHeaders.splice(headerIndex,1);
    }

    myResponseHeaders.push({ name: 'Referrer-Policy', value: 'strict-origin' });


    return {responseHeaders: myResponseHeaders};
}, {urls: ["*://*/*"]}, ['blocking', 'responseHeaders']);

Or with a slightly modified code copied from the documentation:

chrome.webRequest.onHeadersReceived.addListener(
    function(details) {
      for (var i = 0; i < details.responseHeaders.length; ++i) {
        if (details.responseHeaders[i].name === 'Referrer-Policy') {
          details.responseHeaders[i].value = 'strict-origin';
          break;
        }
      }
      return {responseHeaders: details.responseHeaders};
    },
    {urls: ["<all_urls>"]},
    ["blocking", "responseHeaders"]);
Related