Extension manifest permission surface

Paste one browser extension manifest.json and a list of concrete URLs. This page parses every match pattern in the manifest, resolves each URL against each pattern bearing key independently, and prints, per key, whether the URL is granted and via exactly which pattern. Nothing is uploaded. There is no score and no advice.

The six pattern bearing keys, and the two flags that differ

The same match pattern resolves differently depending on which manifest key it sits in. Two flags do all the work: whether the path is matched or ignored, and which URL schemes the key accepts. This table is the reference value of the tool, so it is rendered before you paste anything.

Per key resolution flags, as implemented by this page
Manifest key Path Schemes accepted Source
host_permissions ignored chrome, http, https, file, ftp, ws, wss, uuid-in-package permissions_parser.cc:150 to :152 forces the path to /* after a successful parse. Mask from extension.cc:217 to :221.
optional_host_permissions ignored chrome, http, https, file, ftp, ws, wss, uuid-in-package Same code path, permissions_parser.cc:440 to :447 calls the same parser for both keys.
content_scripts[].matches matched as a glob chrome, http, https, file, ftp, uuid-in-package user_script.cc:69 to :73, narrowed at :109 to :118.
content_scripts[].exclude_matches matched as a glob chrome, http, https, file, ftp, uuid-in-package Same mask as the matches list it sits beside.
externally_connectable.matches matched as a glob any scheme externally_connectable.cc:108 constructs the pattern with SCHEME_ALL.
web_accessible_resources[].matches must be exactly /* any scheme web_accessible_resources_info.cc:120 constructs the pattern with SCHEME_ALL, and :121 to :124 reject the whole manifest unless pattern.path() is exactly /*.

A wildcard scheme is a separate rule that overrides the column above: * narrows to http or https in every key, including the two that otherwise accept any scheme, because SetScheme intersects the mask down to those two the moment it sees *.

Resolve a manifest

Paste the whole manifest.json. Nothing leaves your browser.
Concrete URLs, with a scheme. Blank lines are ignored.

Result

What this tool does not claim

Web accessible resources: the gate, and the three ways around it

When a manifest declares web_accessible_resources, the matches list is not the only exit. Under manifest version 3 the resolution is entry.matches.MatchesURL(initiator_url) inside IsResourceWebAccessibleImpl, at web_accessible_resources_info.cc:231, and the function returns false when nothing matches. The other ways through are a chrome-extension:// initiator via allow_all_extensions or a listed extension_ids entry, and the legacy bypass at :199 to :201, which applies only when manifest_version is below 3. This page prints all of them beside the entry rather than implying matches is the whole gate.

What this page reports is which pages may load your extension's files. It does not compute a fingerprinting verdict. The reason the default is empty is worth reading in the documentation's own words, once, as a quotation and not as this tool's output:

"By default no resources are web accessible, as this allows a malicious website to fingerprint extensions that a user has installed or exploit vulnerabilities (for example XSS bugs) in installed extensions." Chrome for Developers, web_accessible_resources reference. The same page states: "A navigation from a web origin to an extension resource is blocked unless the resource is listed as web accessible."

Grammar

A match pattern has four components, not three. The documentation gives the structure as <scheme>://<host>:<port>/<path> and states that the port is optional and "By default, this is treated as a wildcard with the same behavior as :*", and that "Match patterns match all ports unless an explicit port is specified."

The ordering inside the parser is the part that a three component implementation gets wrong. The port is split off the authority before the host wildcard rule is applied. Chromium finds the : separator inside host_and_port at url_pattern.cc:269 to :300 and only then validates the host, and MatchesPortPattern at :907 is the whole of the port comparison: return port_ == "*" || port_ == port;. Validate the host first and http://*:*/* dies with a host wildcard error, taking every explicit port pattern with it. That row is in the self test above, and so is the Chromium test case http://fo.*.ba:123/baz, which reports a host wildcard error only if the port was removed first.

Three more rules that surprise people, all verified against the source rather than the prose:

Sources

Every line number on this page was read from the file it names, in the main branch, on 2026-09-08. Line numbers move as the branch moves; the function names do not.

Independent and unaffiliated with Google, Chromium or any browser vendor. Behaviour was reimplemented from the published specifications and source listed above. No third party code is reproduced here. MIT licensed, Copyright (c) 2026 0xelitesystem. Built by elitesystem.ai