# Sensitive APIs restricted (camera, microphone, geolocation)

- **Pattern:** `ab-002445` (`security-headers-ii.permissions-depth.sensitive-apis-restricted`)
- **Severity:** high
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-002445
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-002445)

## Why it matters

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.

## Severity rationale

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.

## Remediation

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)`.

```js
// 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.

## Detection

- **ID:** `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:

  ```js
  headers: [{
    key: 'Permissions-Policy',
    value: 'camera=(), microphone=(), geolocation=()'
  }]
  ```

  If your app does use one of these APIs, restrict it to same-origin: `camera=(self)`.

## External references

- cwe CWE-693
- owasp A05

Taxons: access-control

HTML version: https://auditbuffet.com/patterns/ab-002445
