Qué puede bloquear realmente el encabezado Permissions-Policy
Una guía práctica sobre las funciones del navegador que puedes restringir, lo que no puedes controlar y cómo desplegar el encabezado sin romper funcionalidades útiles.
Tabla de contenido
- La versión corta
- Qué controla Permissions-Policy
- Qué puede bloquear en tus propias páginas
- Qué puede bloquear en iframes
- Qué no puede bloquear
- Una política predeterminada sensata
- Cómo desplegarlo sin romper cosas
- 1. Inventaría el uso de funciones
- 2. Empieza en un entorno de bajo riesgo
- 3. Usa políticas específicas por página cuando sea necesario
- 4. Verifica la respuesta real
- 5. Documenta las excepciones
- Errores comunes de sintaxis
- El valor práctico para la privacidad
La versión corta
Permissions-Policy es un encabezado de respuesta HTTP que permite a un sitio limitar el acceso a determinadas funciones del navegador: cámara, micrófono, geolocalización, pantalla completa, pagos, sensores y una larga lista de APIs menores.
No es un escudo de privacidad general. No detendrá todo el seguimiento, no bloqueará cookies, no impedirá solicitudes de red ni hará que el JavaScript de terceros sea seguro. Lo que sí puede hacer bien es más acotado y aun así valioso: reducir las capacidades del navegador disponibles para tus propias páginas y para los marcos incrustados.
Esto importa porque los sitios web modernos se componen de fragmentos de analítica, embeds de medios, widgets de chat, gestores de consentimiento, scripts publicitarios, mapas, flujos de pago y experimentos internos. La mayoría de esos componentes no necesitan acceso a APIs potentes del dispositivo. Una buena política lo deja explícito.
Si ya estás revisando encabezados en producción, acompaña este trabajo con una comprobación directa de la respuesta real. Nuestra guía sobre depurar redirecciones y encabezados HTTP en producción cubre el hábito que importa aquí: inspeccionar lo que el navegador recibe realmente, no lo que tu archivo de configuración dice que debería ocurrir.
Qué controla Permissions-Policy
El encabezado controla el acceso a funciones nombradas del navegador. La lista exacta cambia con el tiempo porque las APIs del navegador cambian, pero las directivas habituales incluyen:
cameramicrophonegeolocationfullscreenpaymentusbbluetoothaccelerometergyroscopemagnetometerscreen-wake-lockclipboard-readclipboard-writepublickey-credentials-getinterest-cohorten debates antiguos, ahora mayoritariamente histórico
Una directiva puede permitir una función para nadie, para el origen actual o para orígenes seleccionados. Por ejemplo:
Permissions-Policy: camera=(), microphone=(), geolocation=(self)
Esto significa que la cámara y el micrófono están deshabilitados para el documento y sus contextos de navegación anidados, mientras que la geolocalización solo está permitida para el mismo origen.
Un ejemplo más permisivo:
Permissions-Policy: geolocation=(self "https://maps.example"), fullscreen=(self "https://video.example")
Esto permite que tu propio origen y un proveedor de mapas concreto usen geolocalización, y que tu propio origen más un proveedor de vídeo soliciten pantalla completa.
La política la evalúa el navegador. Si una función no está permitida, el JavaScript que use esa API debería fallar o comportarse como si no estuviera disponible. El modo exacto de fallo depende de la API. A veces una promesa se rechaza. A veces una capacidad simplemente no parece utilizable.
Qué puede bloquear en tus propias páginas
En páginas propias, Permissions-Policy es más útil como barrera de seguridad. Reduce el radio de impacto del código accidental o inesperado.
Una página de marketing, por ejemplo, probablemente no necesita el micrófono, la cámara, Bluetooth, USB, sensores de movimiento ni APIs de pago. Puedes denegar esas funciones de forma global:
Permissions-Policy: camera=(), microphone=(), bluetooth=(), usb=(), payment=(), accelerometer=(), gyroscope=(), magnetometer=()
Eso no hace que todos los scripts de la página sean confiables. Sí significa que, si un experimento de un tag manager, una dependencia comprometida o un widget pegado intenta llamar a una API restringida, el navegador no debería concederle acceso.
Para equipos con muchos colaboradores, este es un valor predeterminado útil. Cambia la conversación de una confianza difusa a una capacidad explícita. Si una función futura necesita realmente la cámara, alguien tiene que cambiar la política y explicar por qué.
Ese es el tipo correcto de fricción.
Qué puede bloquear en iframes
El encabezado se vuelve especialmente útil alrededor del contenido incrustado.
Los navegadores ya tratan los iframes como contextos de navegación separados, pero el contenido de terceros incrustado aún puede solicitar funciones potentes si la política y los atributos del iframe lo permiten. Permissions-Policy permite que la página padre establezca un límite superior.
Por ejemplo, si tu página incrusta un reproductor de vídeo, un widget de soporte y un mapa, puedes evitar dar a todos los marcos acceso a todas las funciones. Podrías permitir pantalla completa solo para el marco de vídeo y geolocalización solo para el marco del mapa.
Hay dos capas que conviene entender:
- El encabezado HTTP
Permissions-Policyestablece la política para el documento. - El atributo
allowdel iframe puede delegar funciones específicas a un marco, pero solo dentro de lo que permite la política del padre.
Un iframe sencillo podría verse así:
<iframe src="https://video.example/embed/123" allow="fullscreen"></iframe>
Si tu encabezado deniega por completo la pantalla completa, el atributo del iframe no puede anular esa denegación. Si tu encabezado permite pantalla completa para ese origen, el atributo del iframe puede delegarla.
Esta jerarquía es una de las razones por las que merece la pena usar el encabezado. Da a los equipos de plataforma o seguridad una forma de establecer límites en todo el sitio, sin dejar de permitir que los equipos de producto habiliten embeds específicos cuando sea necesario.
Qué no puede bloquear
Aquí es donde los equipos a veces sobrestiman el encabezado.
Permissions-Policy no reemplaza una política de seguridad de contenido. No decide qué scripts pueden cargarse. No impide que un script envíe datos por la red. No sanea HTML. No previene XSS. No bloquea spam en formularios. Si el problema es el abuso de formularios, empieza por la mecánica descrita en por qué tu formulario de contacto es tu mayor responsabilidad de spam, no por este encabezado.
Tampoco reemplaza la gobernanza de cookies. Las cookies, el almacenamiento local, el consentimiento, los embeds de terceros y las protecciones del navegador contra el seguimiento son cuestiones separadas. Si estás revisando controles de privacidad de forma amplia, el panorama de cookies merece su propia revisión; los cambios prácticos se cubren en qué cambió para las cookies en 2026 y qué hacer al respecto.
Lo más importante: Permissions-Policy no hace privado el JavaScript de terceros. Si cargas un script de terceros en tu página propia, por lo general se ejecuta con los privilegios de tu página, sujeto a otras restricciones del navegador y a tus encabezados de seguridad. Denegar el acceso a la cámara está bien. No impide que ese script lea contenido del DOM, observe acciones del usuario o realice solicitudes de red permitidas.
Para eso necesitas otros controles: selección cuidadosa de proveedores, CSP, iframes con sandbox, Subresource Integrity cuando corresponda, minimización de datos y revisiones aburridas pero necesarias.
Una política predeterminada sensata
No existe un encabezado universal que encaje con todos los sitios, pero la mayoría de los sitios de contenido y marketing pueden empezar de forma restrictiva.
Una primera aproximación razonable:
Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=(), usb=(), bluetooth=(), accelerometer=(), gyroscope=(), magnetometer=(), screen-wake-lock=()
Luego vuelve a añadir solo lo que el sitio use realmente.
Por ejemplo:
- Una tienda que use Payment Request API puede necesitar
payment=(self). - Un buscador de ubicaciones puede necesitar
geolocation=(self)o un origen de mapas confiable. - Una aplicación de conferencias puede necesitar
camera=(self)ymicrophone=(self). - Un sitio con mucho vídeo puede necesitar
fullscreen=(self "https://trusted-video.example").
Lo importante no es copiar una política enorme de una lista de comprobación y darla por terminada. Empieza con tu inventario de funciones. ¿Qué páginas necesitan qué capacidades del navegador? ¿Qué embeds necesitan delegación? ¿Qué funciones resultarían sorprendentes si fueran solicitadas?
Cómo desplegarlo sin romper cosas
Despliega esto como cualquier otro encabezado de producción: deliberadamente.
1. Inventaría el uso de funciones
Busca en tu base de código llamadas a APIs del navegador como getUserMedia, geolocation, requestFullscreen, PaymentRequest, Web Bluetooth, WebUSB y APIs de wake lock.
Luego revisa los embeds de terceros. La documentación de proveedores de vídeo, mapas, pagos e identidad a menudo menciona los valores allow requeridos para iframe.
2. Empieza en un entorno de bajo riesgo
Añade un encabezado restrictivo en staging y prueba los recorridos principales. Presta atención a los mensajes de la consola del navegador. Los navegadores suelen informar cuando una función está bloqueada por la política de permisos.
3. Usa políticas específicas por página cuando sea necesario
No fuerces una única política global si tu producto tiene tipos de página muy diferentes. Un blog, checkout, página de mapa y sala de vídeo probablemente necesitan capacidades distintas.
La mayoría de servidores web, frameworks y plataformas edge pueden establecer encabezados condicionalmente por ruta. Eso suele ser más limpio que debilitar todo el sitio por una sola función.
4. Verifica la respuesta real
Los encabezados pueden ser añadidos, sobrescritos, duplicados o eliminados por CDNs, proxies inversos, servidores de aplicación y middleware. Comprueba la respuesta final en browser DevTools o con herramientas de línea de comandos.
Prueba también los contextos incrustados. Que una página de nivel superior parezca correcta no garantiza que un iframe haya recibido la delegación que pretendías.
5. Documenta las excepciones
Cada función permitida debería tener un responsable y una razón. Esto suena burocrático hasta que, seis meses después, nadie recuerda por qué geolocation se abrió a un dominio de proveedor que ya no aparece en la página.
Errores comunes de sintaxis
La sintaxis moderna del encabezado es compacta, pero es fácil equivocarse ligeramente.
Usa paréntesis vacíos para denegar una función:
Permissions-Policy: microphone=()
Usa self para el origen actual:
Permissions-Policy: geolocation=(self)
Usa orígenes entre comillas para orígenes externos específicos:
Permissions-Policy: fullscreen=(self "https://video.example")
Evita basarte en ejemplos antiguos de Feature-Policy salvo que estés dando soporte intencionado a comportamiento heredado. El encabezado antiguo usaba una sintaxis diferente y no es aquello sobre lo que deberías diseñar hoy.
Recuerda también que el soporte del navegador varía según la directiva. Un navegador puede soportar el encabezado pero no una directiva de función concreta. Es normal. Trata el encabezado como una medida de defensa en profundidad, no como tu único control de privacidad o seguridad.
<!-- tool-cta:start -->
💡 Prueba esto: Verifica que tu Permissions-Policy se esté entregando según lo previsto con Get Headers, que muestra los encabezados de respuesta sin procesar que envía tu servidor.
<!-- tool-cta:end -->
El valor práctico para la privacidad
El valor de privacidad de Permissions-Policy no es que haga que un sitio sea anónimo o libre de rastreadores. No lo hace.
Su valor es que estrecha el acceso a capacidades sensibles del navegador. Ubicación, cámara, micrófono, sensores del dispositivo, APIs de hardware local y flujos de pago son potentes. La mayoría de las páginas no los necesitan. Muchos componentes incrustados nunca deberían poder pedirlos.
Eso es una mejora real. Reduce avisos accidentales, limita la exposición innecesaria de capacidades y da a tu equipo un artefacto concreto para revisar cuando se publica nueva funcionalidad.
La mejor versión de este encabezado es aburrida: restrictiva por defecto, relajada solo donde una función visible para el usuario lo requiera y probada como parte del proceso normal de lanzamiento.