← Home ← Codex ← DEBT ← Engine
Browse by Category
+ added · updated 7d
← Back to glossary

Permissions API

JavaScript HTML5 Intermediate
debt(d7/e3/b3/t7)
d7 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'only careful code review or runtime testing' (d7). No automated linting or static analysis tool in detection_hints.tools catches missing permission checks. The code_pattern hint (permissions.query) requires manual inspection or runtime testing to identify when permission state isn't checked before API calls.

e3 Effort Remediation debt — work required to fix once spotted

Closest to 'simple parameterised fix' (e3). The quick_fix describes a straightforward pattern: add permissions.query() before the feature, branch on state (granted/prompt/denied), and add onchange listener. This refactor is localized to the component using the sensitive API and doesn't require cross-cutting changes.

b3 Burden Structural debt — long-term weight of choosing wrong

Closest to 'localised tax' (b3). The choice to properly check permissions applies only to components that use sensitive APIs (geolocation, camera, microphone, etc.). Once a component implements the pattern, the tax is paid locally; other components unaffected. applies_to scope is 'web' contexts only, limiting reach.

t7 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'serious trap' (t7). The canonical misconception directly contradicts intuition: query() does NOT request permissions — it only checks state. Developers unfamiliar with the distinction will assume query() triggers the browser prompt, when the actual request happens only on the underlying API call. This is a documented gotcha (mentioned in misconception) that contradicts the obvious naming expectation.

About DEBT scoring →

TL;DR

The Permissions API (navigator.permissions.query()) lets you check the current state of browser permissions — granted, denied, or prompt — before requesting sensitive APIs.

Explanation

navigator.permissions.query({ name: 'geolocation' | 'camera' | 'clipboard-read' | 'notifications' | ... }) returns a PermissionStatus with state: 'granted', 'denied', or 'prompt'. Subscribe to changes with status.onchange. Use cases: show appropriate UI (enable location button vs 'go to settings' message), avoid triggering permission prompts at bad times. Supported permissions vary by browser. Not all APIs have a corresponding permission entry — check MDN for coverage. Chrome, Firefox, and Safari have different support levels.

Common Misconception

Checking permissions with the Permissions API is the same as requesting them — query() checks without requesting. The actual request happens when you call the API (e.g., geolocation.getCurrentPosition).

Why It Matters

Querying permissions before prompting allows showing context-aware UI — not prompting when denied (show 'enable in settings' instead), or prompting at the right moment.

Common Mistakes

  • Not checking permission before showing a feature that requires it.
  • Assuming query() is available for all permissions — coverage varies by browser.
  • Not reacting to permission state changes (onchange event).

Code Examples

✗ Vulnerable
// Immediately request — no context for user:
navigator.geolocation.getCurrentPosition(success, error);
✓ Fixed
const status = await navigator.permissions.query({ name: 'geolocation' });

if (status.state === 'granted') {
    navigator.geolocation.getCurrentPosition(success);
} else if (status.state === 'prompt') {
    showLocationRequestButton(); // User hasn't decided
} else {
    showEnableInSettingsMessage(); // Denied
}

status.onchange = () => updateUI(status.state);

Added 23 Mar 2026
Edited 5 Apr 2026
Views 123
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings F 2 pings S 0 pings S 1 ping M 2 pings T 0 pings W 0 pings T 1 ping F 0 pings S 0 pings S 0 pings M 2 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 1 ping T 0 pings W 0 pings T 0 pings F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 1 ping T 3 pings F 1 ping S
Amazonbot 1
PetalBot 1 Ahrefs 1 Bing 1
ChatGPT 13 Google 11 Amazonbot 11 PetalBot 8 Scrapy 7 Ahrefs 6 Perplexity 5 SEMrush 5 Unknown AI 4 Brave Search 4 Claude 3 Applebot 3 Meta AI 2 Bing 2 Majestic 1 Twitter/X 1 Baidu 1
crawler 81 crawler_json 4 pre-tracking 2
🧱 FUNDAMENTALS — new to this? Start with the ground floor.
JavaScript javascript The programming language of the browser — it reads and modifies the page (the DOM), reacts to user events, and fetches data without reloading.

JavaScript is the only language browsers execute, so every interactive behaviour on the web goes through it. Its two defining traits — single-threaded event loop and loose typing (== coercion) — explain the majority of both its bugs and its design patterns.

💡 Default to const, use === always, and reach for let only when a value genuinely reassigns.

Ask Codex about JavaScript →
DEV INTEL Tools & Severity
🟢 Low ⚙ Fix effort: Low
⚡ Quick Fix
Query permission state before requesting sensitive APIs. Show appropriate UI for each state (granted/prompt/denied). Listen to onchange for state updates.
📦 Applies To
javascript HTML5 web
🔗 Prerequisites
🔍 Detection Hints
permissions.query
Auto-detectable: ✗ No
🤖 AI Agent
Confidence: Low False Positives: High ✗ Manual fix Fix: Low Context: Function


✓ schema.org compliant