Legacy Feature-Policy header also set
Why it matters
Safari does not recognize the Permissions-Policy header name — it only supports the older Feature-Policy header. Sites that configure Permissions-Policy without a matching Feature-Policy leave Safari users with no API restrictions at all: camera, microphone, geolocation, and payment APIs remain unrestricted for embedded content. CWE-693 applies when a protection mechanism is deployed in a way that bypasses it for a significant user segment. OWASP A05 flags browser-specific security header gaps as misconfiguration — partial cross-browser coverage is operationally equivalent to no coverage for affected users.
Severity rationale
Low because Safari's market share is significant (especially on mobile), and omitting `Feature-Policy` leaves that entire segment without any API permissions restrictions despite `Permissions-Policy` being configured.
Remediation
Set both Permissions-Policy (Chromium/Firefox) and Feature-Policy (Safari) with matching restrictions. The syntax differs: Feature-Policy uses 'none' instead of () and semicolons instead of commas.
headers: [
{
key: 'Permissions-Policy',
value: 'camera=(), microphone=(), geolocation=()'
},
{
key: 'Feature-Policy',
value: "camera 'none'; microphone 'none'; geolocation 'none'"
}
]
Skip this step only if you have confirmed your deployment target is Chromium-only (Chrome extension, Electron app, kiosk). For public web apps, both headers are required.
Detection
-
ID:
feature-policy-compat -
Severity:
low -
What to look for: Check for both
Permissions-Policy(modern) andFeature-Policy(legacy) headers. Safari does not support the newerPermissions-Policyname. Both headers should be present with matching restrictions for cross-browser coverage. -
Pass criteria: Both
Permissions-PolicyandFeature-Policyheaders are present with matching restrictions — at least 3 APIs restricted in each. Count the number of restricted APIs in each header and verify they match. -
Fail criteria: Only
Permissions-Policyis set without a correspondingFeature-Policyheader, or vice versa. -
Skip (N/A) when: No
Permissions-Policyheader configured. Also skip if the project explicitly targets Chromium-only (e.g., Chrome extension, Electron app). -
Detail on fail:
"Permissions-Policy header set but no legacy Feature-Policy — Safari users have no API restrictions"or"Feature-Policy present but missing modern Permissions-Policy header" -
Remediation: Set both headers for cross-browser compatibility. The syntax differs slightly:
headers: [ { key: 'Permissions-Policy', value: 'camera=(), microphone=(), geolocation=()' }, { key: 'Feature-Policy', value: "camera 'none'; microphone 'none'; geolocation 'none'" } ]Feature-Policyuses'none'instead of()and semicolons instead of commas. This is a low-priority compatibility improvement.
External references
- cwe · CWE-693
- owasp:2021 · A05
Taxons
History
- 2026-04-18·v1.0.0·Initial import from security-headers-ii·automated