Permissions Policy Middleware
raw JSON →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.
Common errors
error TypeError: permissionsPolicy is not a function ↓
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 ↓
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 ↓
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. Warnings
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. ↓
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. ↓
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. ↓
Install
npm install permissions-policy yarn add permissions-policy pnpm add permissions-policy Imports
- permissionsPolicy wrong
import { permissionsPolicy } from 'permissions-policy';correctimport permissionsPolicy from 'permissions-policy'; - permissionsPolicy wrong
const { permissionsPolicy } = require('permissions-policy');correctconst permissionsPolicy = require('permissions-policy'); - PermissionsPolicyOptions
import type { PermissionsPolicyOptions } from 'permissions-policy';
Quickstart
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.');
});