How Permissions Policy Restricts JavaScript Features

The Permissions Policy HTTP header allows website owners to explicitly enable, restrict, or disable access to sensitive browser features and hardware APIs for both the main document and embedded third-party frames. This article explains how the Permissions Policy header functions, breaks down its syntax and directives, demonstrates how it enforces restrictions against JavaScript execution, and details the security benefits it offers against unauthorized API usage.

What is the Permissions Policy Header?

Permissions Policy (formerly known as Feature Policy) is a standard HTTP response header that defines a security contract between a web server and the client browser. By declaring a set of directives, a server informs the browser which powerful web platform APIs—such as geolocation, camera access, microphone inputs, or autoplay—are permitted to run in the current context.

When a browser receives this header, it configures internal permission registries before executing page scripts. If a script attempts to invoke a disabled API, the browser immediately blocks execution at the platform level, preventing unauthorized access regardless of user settings or script privileges.

How Permissions Policy Interacts with JavaScript

Permissions Policy enforces restrictions deterministically at the browser runtime level, altering how standard JavaScript APIs behave:

  1. Immediate Promise Rejections: APIs that rely on JavaScript Promises fail automatically. For example, invoking navigator.mediaDevices.getUserMedia() when the camera policy is disabled will immediately reject with a NotAllowedError or SecurityError DOMException without prompting the user.
  2. Synchronous Failures: Synchronous properties or methods associated with blocked features either return false, return undefined, or throw an error. For instance, document.requestFullscreen() will fail and trigger a fullscreenerror event.
  3. Integration with the Permissions API: Scripts can inspect policy restrictions programmatically using navigator.permissions.query(). If a feature is disabled by Permissions Policy, the permission state will report as denied, allowing developers to write fallback logic.
// Example: Querying the state of an API restricted by Permissions Policy
navigator.permissions.query({ name: 'geolocation' }).then((result) => {
  if (result.state === 'denied') {
    console.warn('Geolocation is blocked by Permissions Policy.');
  }
});

Syntax and Directive Structure

The Permissions Policy header uses a structured header syntax consisting of feature names assigned to allowlists:

Permissions-Policy: <feature>=(<allowlist>), <feature>=(<allowlist>)

Allowlist Values

Example Header Configurations

Restricting Embedded Content (iFrames)

Permissions Policy provides strict control over third-party scripts loaded through <iframe> elements. By default, powerful features disabled in the top-level document’s HTTP header cannot be enabled by an iframe, even if the iframe attempts to override the policy.

To grant an allowed feature to an iframe, the parent document must explicitly pass permission using the iframe’s allow attribute:

<!-- Grants camera access to an embedded partner, assuming the HTTP header permits it -->
<iframe src="https://trusted-partner.com/meeting" allow="camera"></iframe>

If the parent document’s HTTP header disables the feature with camera=(), any allow="camera" attribute defined on an iframe will be ignored, maintaining absolute enforcement from the server’s policy.

Security Benefits

Implementing the Permissions Policy header provides several core security advantages: