Skip to content

Inconsistency: tabs.query behavior for permissions granted by content_scripts.matches #915

@muzuiget

Description

@muzuiget

I've discovered an inconsistency between Chrome and Firefox in how chrome.tabs.query handles host permissions that are implicitly granted by content_scripts.matches.

Consider the following manifest.json:

{
    "manifest_version": 3,
    "name": "Example",
    "version": "0.1.0",
    "action": {
        "default_popup": "popup.html"
    },
    "content_scripts": [
        {
            "world": "ISOLATED",
            "matches": [
                "https://www.example.com/*"
            ],
            "js": [
                "isolated.js"
            ]
        }
    ]
}

The content_scripts.matches field implicitly grants host permissions for https://www.example.com/*.

However, when using chrome.tabs.query() from a popup on https://www.example.com/, the behavior differs between browsers.

Code in popup.html:

const tabs = await chrome.tabs.query({currentWindow: true, active: true});
const tab = tabs[0];
console.log(tab.url, tab.title);

Observed Behavior:

  • Firefox: "https://www.example.com/" "Example Domain"
  • Chrome: undefined undefined

To get the expected result in Chrome, I must explicitly and redundantly declare the same origin in host_permissions:

{
    "manifest_version": 3,
    "name": "Example",
    "version": "0.1.0",
    "host_permissions": [
        "https://www.example.com/*"
    ],
    "action": {
        "default_popup": "popup.html"
    },
    "content_scripts": [
        {
            "matches": [
                "https://www.example.com/*"
            ],
            "js": [
                "isolated.js"
            ]
        }
    ]
}

With this change, Chrome correctly returns the url and title.

This suggests that Chrome's implementation of tabs.query does not respect the permissions granted by content_scripts, and instead relies solely on the explicit host_permissions declaration.

I believe Chrome's behavior should be aligned with Firefox's. If an extension has permission to inject a content script into a page, it should intuitively have permission to access that tab's basic metadata like URL and title via tabs.query. This change would simplify manifest files and remove the need for workarounds like using chrome.tabs.sendMessage() to probe for the tab's URL.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions