Permissions Policy Middleware

raw JSON →
0.6.0 verified Thu Apr 23 auth: no javascript

The `permissions-policy` package provides Express and Connect middleware for managing the `Permissions-Policy` HTTP header. This header controls which browser features and APIs (like camera, microphone, geolocation) are available to a document and its iframes, enhancing web security. It is the modern successor to the deprecated `Feature-Policy` header and is built upon the foundational work of Evan Hahn, a well-known contributor to web security middleware (e.g., Helmet). Currently stable at version 0.6.0, the package receives periodic updates, with recent releases focusing on improved ESM exports and increased flexibility in defining policy directives. Its primary differentiator is its dedicated, streamlined focus on this single, crucial security header, making it an ideal component for integration into broader security middleware suites.

error TypeError: permissionsPolicy is not a function
cause This usually indicates an incorrect import or require statement, especially when mixing CommonJS and ES Modules syntax, or if the module resolution is misconfigured.
fix
For ESM, use import permissionsPolicy from 'permissions-policy';. For CommonJS, use const permissionsPolicy = require('permissions-policy');. Verify your tsconfig.json (if TypeScript) and package.json type field are correctly configured for your project's module system.
error ReferenceError: require is not defined in ES module scope
cause You are attempting to use `require()` within an ES module file (`.mjs` or a `.js` file when `type: "module"` is set in `package.json`).
fix
Change your import statement to use ESM syntax: import permissionsPolicy from 'permissions-policy';. If you need to use CommonJS modules, ensure your file is treated as CommonJS (e.g., .cjs extension or type: "commonjs" in package.json).
error Permissions-Policy header not present in response
cause The middleware might not be active, or it's placed too late in the Express/Connect middleware chain after the response has already been sent or modified.
fix
Ensure app.use(permissionsPolicy(...)) is called early in your application's setup, typically before any route handlers or other middleware that might send a response. Also, verify that the features configuration object is correctly structured and not empty.
breaking The `Feature-Policy` HTTP header, which this package is based on, has been officially deprecated in favor of `Permissions-Policy`. While this middleware sets the current standard, users migrating from older `Feature-Policy` implementations should ensure they update their policies and expectations accordingly.
fix Ensure you are using the `Permissions-Policy` header and its syntax, as `Feature-Policy` is no longer supported by modern browsers.
gotcha Since version 0.6.0, the middleware has removed internal restrictions on which directives (feature names) can be set. This means any key provided in the `features` object will be included in the header, even if it's not a standard or officially supported Permissions Policy directive. This offers flexibility but removes a layer of validation that might have caught typos or unsupported features in previous versions.
fix Carefully review all feature names and their values in your configuration to ensure they are valid Permissions Policy directives, especially when adding new or experimental ones. The middleware will no longer prevent potentially invalid directives from being sent.
gotcha Starting with version 0.5.0, the package exports were changed to prioritize ES6 modules for smaller bundle sizes. While dual-packaging is generally supported, some older CommonJS-only environments or specific bundler configurations might encounter issues if they do not correctly resolve the CommonJS entry point.
fix For CommonJS environments, ensure your Node.js version supports dual-packaging correctly, or if using a bundler, confirm it correctly interprets the `main` or `exports` field in the package's `package.json`. For modern applications, prefer ESM imports: `import permissionsPolicy from 'permissions-policy';`.
npm install permissions-policy
yarn add permissions-policy
pnpm add permissions-policy

This quickstart initializes an Express app and applies the `permissions-policy` middleware to set the `Permissions-Policy` HTTP header with common feature configurations, demonstrating how to enable or disable various browser APIs for a web application.

import express from 'express';
import permissionsPolicy from 'permissions-policy';
import { Request, Response, NextFunction } from 'express';

const app = express();
const port = 3000;

// Apply the permissions-policy middleware early in your middleware chain.
app.use(
  permissionsPolicy({
    features: {
      fullscreen: ['self'],          // Allows fullscreen requests from the current origin.
      vibrate: ['none'],             // Disables the Vibration API entirely.
      payment: ['self', 'https://example.com'], // Allows Payment Request API from 'self' and 'example.com'.
      syncXhr: [],                   // Disables synchronous XMLHttpRequest.
      accelerometer: ['self'],       // Allows accelerometer access from 'self'.
      camera: ['*'],                 // Allows camera access from any origin (use with caution).
      interestCohort: ['*']          // Allows FLoC/Interest Cohort API from any origin.
    },
    // Custom or experimental directives can be added since v0.6.0
    'my-experimental-feature': ['self', 'https://cdn.my-site.com'],
  })
);

app.get('/', (req: Request, res: Response) => {
  res.send('Hello! Check your response headers for Permissions-Policy.');
});

app.get('/test-policy', (req: Request, res: Response) => {
  res.status(200).send('This page has a Permissions-Policy header set.');
});

app.listen(port, () => {
  console.log(`Server listening at http://localhost:${port}`);
  console.log('Open http://localhost:3000 in your browser and inspect network headers.');
});