Security Auditor — checks that the
Permissions-Policy response header is present, parses, and keeps sensitive browser features away from code you do not control.Security
Stops injected scripts and embedded frames from asking visitors for their camera, microphone or location.
Standards
Follows the W3C Permissions Policy specification and the W3C feature registry.
Permissions-Policy header tells the browser which features (camera, microphone, geolocation, payment, USB and many more) the page and the frames it embeds may use. This auditor reads that header from the audited URL and checks that it is valid and that sensitive features are not left open.
How it works
- Fetch — sends a
HEADrequest (orGETwhenHEADis not supported) to the audited URL as 37AuditsBot. A blocked request ends the audit with590; any other failure (timeout, DNS, TLS, non-2xx answer) ends it with500. - Read — collects every
Permissions-Policyheader line and joins them, as browsers do. - Parse — splits the header into members and reads each as
feature=allowlist. Both forms the specification allows are accepted: an inner list such ascamera=(self "https://a.example")and a single item such ascamera=*,camera=selforcamera="https://a.example". Parameters after;(for example;report-to=main) are ignored. - Rules — a missing header stops the audit with
400. Otherwise every rule runs: malformed members (401), sensitive features open to every origin (402), unknown feature names (300), expected sensitive features left unset (301) and retired features (302). - Aggregate —
FAILwins overWARNING; when every rule passes the audit isSUCCESS(200). - Specification pin — every run emits
37A-PermissionsPolicyAuditor-100(INFORMATION), naming the W3C Permissions Policy Working Draft of 2026-09-22. It does not change the overall status.
ch-* name (Client Hints delegation, such as ch-dpr or ch-save-data) is known. Names in the registry’s Retired Features section get their own warning instead.
Sensitive features (402): camera, microphone, geolocation, payment, usb, bluetooth, serial, hid, clipboard-read, clipboard-write, display-capture. Expected features (301): camera, microphone, geolocation, payment.
What it audits
Every row maps to onecheckRule* method and one CheckCode, in the order the auditor runs them. Rules 401–302 are skipped when the header is missing (400). CheckCode suffixes use status ranges: 100 information, 200 success, 300–399 warning, 400–499 fail, 500–599 error.
Output documentation
Risks and considerations
Why the header matters
- Without a policy, the page and every frame it embeds with an
allowattribute can request powerful features. An injected script or a compromised third-party widget can then prompt visitors for their camera, microphone or location, and the prompt carries your site’s name. feature=()disables a feature everywhere on the page;feature=(self)allows it only for your own origin. Allow the minimum the page needs.
Parsing is all-or-nothing
- The header is a Structured Fields dictionary. A browser that cannot parse it drops the whole header, so one malformed member removes every restriction in it.
Feature names change
- Browsers silently ignore unknown names, so a typo leaves the feature at its default. Retired names such as
window-placement(renamedwindow-managementin Chrome 111) no longer have any effect. - The known-feature list is a copy of the W3C registry. A brand-new feature may be reported as unknown (
300) until the list is refreshed.
What this auditor does not check
- The legacy
Feature-Policyheader and theallowattribute on iframes are not read. - Only the audited URL is fetched; other pages of the site may send a different policy.