Camera, microphone, and geolocation are the three browser APIs with direct real-world privacy consequences: an app that inadvertently grants a third-party script access to the mic or camera exposes users to surveillance, and geolocation exposure is a physical safety risk. Without Permissions-Policy restrictions, embedded ads, analytics scripts, or compromised CDN resources can request these sensitive APIs. CWE-693 applies — the browser's permission prompt is a protection mechanism, but a missing Permissions-Policy allows any embedded script to trigger that prompt, bypassing user intent. OWASP A05 flags unnecessary API exposure as a security misconfiguration.
High because unrestricted access to camera, microphone, and geolocation APIs by embedded third-party content exposes users to surveillance and physical location tracking with no application-level gate.
Disable all three sensitive APIs in Permissions-Policy unless your application actively uses them. If you do use one, restrict it to same-origin with (self).
// next.config.js
headers: [{
source: '/(.*)',
headers: [{
key: 'Permissions-Policy',
value: 'camera=(), microphone=(), geolocation=()'
}]
}]
For a Next.js app that uses geolocation for location-based features: geolocation=(self) restricts the API to your origin only, blocking embedded content from requesting location while preserving your own functionality.
ID: security-headers-ii.permissions-depth.sensitive-apis-restricted
Severity: high
What to look for: Parse the Permissions-Policy header value. Check whether camera, microphone, and geolocation — the 3 most privacy-sensitive browser APIs — are each set to () (disabled for all origins). Count each: camera, microphone, geolocation.
Pass criteria: All 3 sensitive APIs are set to (). Count the restricted APIs and report: "X of 3 sensitive APIs restricted."
Fail criteria: Fewer than 3 of camera, microphone, geolocation are set to ().
Skip (N/A) when: No Permissions-Policy header configured (defer to Security Headers & Basics for basic presence).
Cross-reference: For basic Permissions-Policy presence, the Security Headers & Basics audit covers this.
Detail on fail: "X of 3 sensitive APIs restricted — missing: camera, geolocation" or "Permissions-Policy header present but does not restrict microphone — browser default allows embedded content to request mic access"
Remediation: Unless your app actively uses camera, microphone, or geolocation, disable them to prevent embedded content (ads, third-party widgets) from requesting these permissions:
headers: [{
key: 'Permissions-Policy',
value: 'camera=(), microphone=(), geolocation=()'
}]
If your app does use one of these APIs, restrict it to same-origin: camera=(self).