v149 · permissions policy · origin trial
Permissions Policy: focus-without-user-activation
A new permissions policy that lets embedders block programmatic focus from embedded iframes unless the focus is triggered by a genuine user gesture. Prevents malicious or poorly-behaved third-party content from stealing input focus without the user's awareness.
focus-without-user-activation policy is in origin trial in Chrome 149–151, with stable ship targeting Chrome 150. Enable for testing with an origin trial token, or via chrome://flags/#enable-experimental-web-platform-features. Check the ChromeStatus entry for the current timeline.
at a glance
| Origin trial in | Chrome 149–151 |
|---|---|
| Expected stable ship | Chrome 150 |
| Spec | WHATWG HTML PR #10672 |
| Policy explainer | w3c/webappsec-permissions-policy — focus-without-user-activation.md |
| ChromeStatus | 5179186249465856 — Permissions Policy: focus-without-user-activation |
why it exists
Embedding third-party content in an iframe is common — payment widgets, maps, video players, comment sections. These embeds run in their own browsing context and can call element.focus() at any time, including to shift focus away from the user's current interaction. A malicious embed could use this to intercept keystrokes (by focusing a hidden text input), suppress keyboard shortcuts, or disrupt an in-progress form fill on the parent page.
The focus-without-user-activation permissions policy gives the embedder a declarative way to restrict this: when the policy is denied for a frame, any programmatic focus operation in that frame (and its descendants) that is not directly triggered by a user gesture is silently ignored.
shape of the API
What the policy controls
When the policy is denied for a browsing context, the following focus operations are blocked unless there is an active user gesture in the current task:
element.focus() | Scripted focus calls on any element. |
|---|---|
window.focus() | Focus requests from a window to itself or a child window. |
autofocus attribute | Automatic focusing of form controls on load. |
dialog.showModal() | Modal dialogs that would automatically receive focus. |
| Popover focus | Popovers that would auto-focus their first interactive child. |
User-initiated focus (clicking, tabbing via keyboard) is never affected by this policy.
Focus delegation exception
A parent frame that currently holds focus can delegate that focus to a child iframe programmatically — even if the child has the policy denied. This allows legitimate "pass focus into the embed" patterns (e.g. a sign-in button that opens a payment iframe and sets focus to the first field). Once the frame has focus, it can move focus freely within its own subtree.
Default allowlist
The default allowlist for focus-without-user-activation is * (all frames allowed), preserving existing behaviour. You must explicitly deny it to apply the restriction.
example
Deny focus-without-user-activation for all iframes (HTTP header)
Permissions-Policy: focus-without-user-activation=()
Blocks programmatic focus in all subframes. The main frame is not affected.
Deny for a specific third-party embed
<!-- Block programmatic focus from the third-party embed. -->
<iframe
src="https://embed.example.com/widget"
allow="focus-without-user-activation 'none'"
></iframe>
<!-- Explicitly allow focus for a trusted first-party iframe. -->
<iframe
src="/payment/widget"
allow="focus-without-user-activation 'src'"
></iframe>
Allow the main frame only, deny all subframes
Permissions-Policy: focus-without-user-activation=(self)
With this header, embedded iframes cannot focus elements programmatically unless the user has interacted with them first.
Feature detection (JavaScript)
// Check if the policy controls focus in the current frame.
const allowed = document.featurePolicy
? document.featurePolicy.allowsFeature("focus-without-user-activation")
: true; // Assume allowed if API not present.
if (!allowed) {
// Autofocus or programmatic focus will be ignored here.
console.log("Programmatic focus is restricted in this frame.");
}
browser support
| Chrome | Origin trial 149–151; stable ship targeting 150 |
|---|---|
| Edge | Tracking Chromium |
| Firefox | No signal (as of Chrome 149) |
| Safari | No signal (as of Chrome 149) |
see also
- MDN: Permissions-Policy HTTP header
- MDN: <iframe> — allow attribute
- WHATWG HTML issue #11839 — clarifications on focus across browsing contexts
- WebKit standards position