Skip to main content
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.
The 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

  1. Fetch — sends a HEAD request (or GET when HEAD is not supported) to the audited URL as 37AuditsBot. A blocked request ends the audit with 590; any other failure (timeout, DNS, TLS, non-2xx answer) ends it with 500.
  2. Read — collects every Permissions-Policy header line and joins them, as browsers do.
  3. Parse — splits the header into members and reads each as feature=allowlist. Both forms the specification allows are accepted: an inner list such as camera=(self "https://a.example") and a single item such as camera=*, camera=self or camera="https://a.example". Parameters after ; (for example ;report-to=main) are ignored.
  4. 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).
  5. Aggregate — FAIL wins over WARNING; when every rule passes the audit is SUCCESS (200).
  6. 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.
Known feature names come from the Standardized, Proposed and Experimental sections of the W3C feature registry, plus features Chromium ships that the registry does not list. Any 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 one checkRule* 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 allow attribute 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 (renamed window-management in 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-Policy header and the allow attribute on iframes are not read.
  • Only the audited URL is fetched; other pages of the site may send a different policy.