Acme Co. checkout
Imagine this page is mid-checkout and embedded the third-party widget below to handle
"passkey-based payment confirmation". The integration docs told us to grant
allow="publickey-credentials-create publickey-credentials-get", so we did.
Permissions-Policy: publickey-credentials-{create,get}=(self)
overrides the iframe's allow= attribute. When the iframe tries to call
navigator.credentials.create(), it rejects with NotAllowedError
and a Permissions-Policy violation report fires. The iframe's allow= can
only NARROW what the top-level page already permits — it cannot GRANT a capability the
top-level revoked.
publickey-credentials-create=(self), publickey-credentials-get=(self)
Top-level Permissions-Policy is authoritative. The browser enforces it
before honouring any iframe allow= attribute. Result: the iframe's
allow= still parses, the iframe still loads, but the API itself rejects.
The widget's compromised behaviour cannot reach an actual prompt.
Practical pattern: set publickey-credentials-{create,get}=(self)
at the top level on every page that embeds third-party content. If a specific iframe
actually needs WebAuthn, allowlist it explicitly with
=(self "https://that-origin.example") rather than relying on iframe-level
opt-in.
Activity log
Messages from the iframe (via postMessage) plus any Permissions-Policy violations the browser reports.