Skip to content

fix(macOS): fix three screen capture permission issues in Electron layer#561

Merged
siddharthvaddem merged 3 commits intosiddharthvaddem:mainfrom
auberginewly:fix/electron-screen-capture-permissions
May 9, 2026
Merged

fix(macOS): fix three screen capture permission issues in Electron layer#561
siddharthvaddem merged 3 commits intosiddharthvaddem:mainfrom
auberginewly:fix/electron-screen-capture-permissions

Conversation

@auberginewly
Copy link
Copy Markdown
Contributor

@auberginewly auberginewly commented May 9, 2026

Background

While investigating the screen picker showing "Screen (0) / Window (0)" on macOS, three independent permission bugs were found — all related to but distinct from the NSScreenCaptureUsageDescription fix in PR #554.

Closes #558


Changes

Commit 1 — electron/main.ts: missing screen permissions in Electron allowlists

Both setPermissionCheckHandler and setPermissionRequestHandler only allowed:

["media", "audioCapture", "microphone", "videoCapture", "camera"]

"screen" and "display-capture" were missing.

Impact: when the renderer requests a screen source via getUserMedia (chromeMediaSource: 'desktop'), Electron's own permission layer silently rejects it before macOS TCC is ever consulted.

Fix: add "screen" and "display-capture" to both handler allowlists.


Commit 2 — electron/main.ts + electron/ipc/handlers.ts: no proactive screen permission check

Microphone is checked at startup with getMediaAccessStatus + askForMediaAccess. Camera has a request-camera-access IPC handler. Screen recording had neither — it relied entirely on desktopCapturer.getSources() to implicitly trigger the TCC prompt.

Impact: permission status is never settled at startup, so the system dialog can reappear on subsequent launches — the root cause of #558.

Fix:

  • In app.whenReady(), check getMediaAccessStatus("screen") and trigger the TCC prompt when status is "not-determined", mirroring the mic flow
  • Add request-screen-access IPC handler, symmetric to request-camera-access

Commit 3 — electron-builder.json5: entitlement key misplaced in extendInfo

com.apple.security.device.audio-input is an entitlement key and belongs only in macos.entitlements. Writing it into extendInfo places it in Info.plist where it has no effect and is misleading.

Fix: remove it from extendInfomacos.entitlements already has the correct entry.


Testing

Summary by CodeRabbit

  • New Features

    • Added screen-recording/display-capture support and a cross-platform, user-facing screen access request flow; macOS may now prompt earlier for screen access.
  • Bug Fixes

    • Removed an unnecessary macOS audio-input entitlement to streamline permission prompts and avoid over-requesting.

Review Change Stack

…allowlists

setPermissionCheckHandler and setPermissionRequestHandler only allowed
["media", "audioCapture", "microphone", "videoCapture", "camera"], causing
any renderer-side getUserMedia/desktopCapturer request using a screen source
to be silently denied by Electron before macOS TCC is ever consulted.

Fix: add "screen" and "display-capture" to both handler allowlists.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 9, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1a23372f-377e-4f6c-abb0-75b5fc60d58d

📥 Commits

Reviewing files that changed from the base of the PR and between 44188d2 and 3dd7b85.

📒 Files selected for processing (3)
  • electron-builder.json5
  • electron/ipc/handlers.ts
  • electron/main.ts
✅ Files skipped from review due to trivial changes (1)
  • electron-builder.json5
🚧 Files skipped from review as they are similar to previous changes (1)
  • electron/main.ts

📝 Walkthrough

Walkthrough

App now requests and reports macOS screen-recording permission: entitlement updated, new IPC handler to check/trigger screen access, session permission check/request allowlists include screen and display-capture, and startup triggers screen prompt when status is not-determined. Non-macOS defaults to granted.

Changes

Screen Recording Permissions

Layer / File(s) Summary
Entitlements Configuration
electron-builder.json5
Removed com.apple.security.device.audio-input entitlement from macOS extendInfo.
Screen Access IPC Handler
electron/ipc/handlers.ts
Added request-screen-access IPC handler that reads macOS systemPreferences.getMediaAccessStatus("screen"), returns standardized {success, granted, status} payloads, and triggers a fire-and-forget desktopCapturer.getSources({ types: ["screen"] }) when status is not-determined.
Permission Check Handler
electron/main.ts
Expanded default session permission check to allow screen and display-capture in addition to media/audio/video/camera.
Permission Request Handler
electron/main.ts
Updated permission request allowlist to include screen and display-capture.
macOS Startup Prompt
electron/main.ts
On macOS startup, retains microphone prompt and adds an initial desktopCapturer.getSources({ types: ["screen"] }) when screen status is not-determined to trigger the screen-recording TCC prompt.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • siddharthvaddem/openscreen#554: Complements this PR by adding NSScreenCaptureUsageDescription and the com.apple.security.device.screen-capture entitlement — the paired macOS configuration layer for screen recording permissions.

Suggested reviewers

  • siddharthvaddem

Poem

tiny prompt at morning start,
a polite macOS knock at the heart;
desktopCapturer whispers, "may I peek?"
permissions hum, a system tweak —
screens cleared, the sharing art ✨

(also: nit — lowkey risky to fire-and-forget prompts; kinda cursed but pragmatic.)

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed Title clearly and specifically describes the three screen capture permission fixes being made in the Electron layer, directly matching the changeset.
Description check ✅ Passed Description comprehensively covers all three fixes with clear background, motivation, changes, and testing steps following the template structure.
Linked Issues check ✅ Passed All changes directly address #558: permissions are now checked proactively at startup, added to Electron allowlists, and entitlement entry is corrected.
Out of Scope Changes check ✅ Passed All changes are tightly scoped to the three screen capture permission issues described in #558 with no unrelated modifications.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 085ac2a5cd

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread electron/main.ts Outdated
// desktopCapturer.getSources() calls later (fixes repeated permission dialog).
const screenStatus = systemPreferences.getMediaAccessStatus("screen");
if (screenStatus === "not-determined") {
systemPreferences.askForMediaAccess("screen");
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Stop calling askForMediaAccess with screen

On macOS with ScreenCapture still not-determined, this calls systemPreferences.askForMediaAccess("screen"), but Electron's API only supports microphone and camera for askForMediaAccess and rejects invalid media types. Because this call is not awaited or caught, startup can emit an unhandled rejection and, more importantly, it will not show the Screen Recording TCC prompt this patch relies on; the same unsupported call was also added in the new request-screen-access handler.

Useful? React with 👍 / 👎.

@auberginewly auberginewly force-pushed the fix/electron-screen-capture-permissions branch from 085ac2a to 44188d2 Compare May 9, 2026 21:28
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
electron/main.ts (1)

486-493: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

critical: same askForMediaAccess("screen") bug here too

line 492 has the identical issue as handlers.ts – askForMediaAccess doesn't accept "screen" as a parameter (only "microphone" or "camera"). this will break at runtime.

the good news: you don't actually need it. calling getMediaAccessStatus("screen") on line 490 already triggers the TCC prompt when the status is "not-determined". that's literally how the screen recording permission flow works on macOS.

just remove line 492 and you're golden – the getMediaAccessStatus call handles everything.

🛠️ proposed fix
 	// Request microphone and screen recording permissions from macOS
 	if (process.platform === "darwin") {
 		const micStatus = systemPreferences.getMediaAccessStatus("microphone");
 		if (micStatus !== "granted") {
 			await systemPreferences.askForMediaAccess("microphone");
 		}
 
 		// Screen recording has no programmatic grant API — getMediaAccessStatus triggers
 		// the TCC prompt on first call when status is "not-determined", which is the
 		// intended behaviour. Checking here avoids repeated prompts driven by
 		// desktopCapturer.getSources() calls later (fixes repeated permission dialog).
 		const screenStatus = systemPreferences.getMediaAccessStatus("screen");
-		if (screenStatus === "not-determined") {
-			systemPreferences.askForMediaAccess("screen");
-		}
+		// The getMediaAccessStatus call above already triggered the prompt if needed
 	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@electron/main.ts` around lines 486 - 493, The call to
systemPreferences.askForMediaAccess("screen") is invalid (askForMediaAccess only
accepts "microphone" or "camera") and unnecessary because
systemPreferences.getMediaAccessStatus("screen") already triggers the macOS TCC
prompt when status === "not-determined"; remove the stray
systemPreferences.askForMediaAccess("screen") invocation in electron/main.ts
(the code surrounding systemPreferences.getMediaAccessStatus("screen") should
remain) to prevent the runtime error.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@electron/ipc/handlers.ts`:
- Around line 721-745: In the ipcMain.handle("request-screen-access") handler
remove the invalid call to systemPreferences.askForMediaAccess("screen") (it
only accepts "microphone" or "camera") and leave the
getMediaAccessStatus("screen") checks intact; adjust the branch that currently
calls askForMediaAccess to simply return the not-determined response (e.g., {
success: true, granted: false, status: "not-determined" }) so the handler no
longer invokes the unsupported method (refer to the handler for
"request-screen-access", systemPreferences.askForMediaAccess, and
systemPreferences.getMediaAccessStatus).

---

Duplicate comments:
In `@electron/main.ts`:
- Around line 486-493: The call to systemPreferences.askForMediaAccess("screen")
is invalid (askForMediaAccess only accepts "microphone" or "camera") and
unnecessary because systemPreferences.getMediaAccessStatus("screen") already
triggers the macOS TCC prompt when status === "not-determined"; remove the stray
systemPreferences.askForMediaAccess("screen") invocation in electron/main.ts
(the code surrounding systemPreferences.getMediaAccessStatus("screen") should
remain) to prevent the runtime error.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 290d3c00-3c6e-46cd-a9bc-62f0aa6e54bf

📥 Commits

Reviewing files that changed from the base of the PR and between 5bd17f4 and 085ac2a.

📒 Files selected for processing (3)
  • electron-builder.json5
  • electron/ipc/handlers.ts
  • electron/main.ts

Comment thread electron/ipc/handlers.ts
@auberginewly auberginewly changed the title fix(macOS): 修复 Electron 屏幕捕获权限的三处问题 fix(macOS): fix three screen capture permission issues in Electron layer May 9, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
electron/ipc/handlers.ts (1)

732-737: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

askForMediaAccess("screen") is invalid here and will break type-check/runtime.

lowkey risky + kinda cursed combo: the comment says there’s no API equivalent, but Line 736 still calls it. Remove that call and just return not-determined (or trigger prompt via actual capture flow elsewhere).

Proposed minimal fix
 			// Screen recording has no askForMediaAccess equivalent — calling
 			// getMediaAccessStatus("screen") when status is "not-determined" is
 			// sufficient to trigger the TCC prompt.
 			if (status === "not-determined") {
-				systemPreferences.askForMediaAccess("screen");
 				return { success: true, granted: false, status: "not-determined" };
 			}
#!/bin/bash
# Verify there are no unsupported Electron calls left.
# Expected result after fix: no matches.
rg -nP --type=ts 'askForMediaAccess\("screen"\)'
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@electron/ipc/handlers.ts` around lines 732 - 737, In the ipc handler in
handlers.ts where you handle screen media permission status (the branch checking
if status === "not-determined"), remove the invalid call to
systemPreferences.askForMediaAccess("screen") and simply return { success: true,
granted: false, status: "not-determined" } (or keep the existing return) so you
don't invoke an unsupported Electron API; update any adjacent comment to note
that prompting for screen capture must occur via the actual capture flow instead
of askForMediaAccess.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@electron/main.ts`:
- Around line 490-493: Remove the invalid call to
systemPreferences.askForMediaAccess("screen") and rely solely on
systemPreferences.getMediaAccessStatus("screen") to trigger the TCC prompt;
specifically, delete the askForMediaAccess invocation in the block that checks
screenStatus (look for systemPreferences.getMediaAccessStatus and
systemPreferences.askForMediaAccess in electron/main.ts) and apply the same
removal in the analogous handler in electron/ipc/handlers.ts around the code
that checks screen permission. Ensure no other code expects
askForMediaAccess("screen") to return a promise or value.

---

Duplicate comments:
In `@electron/ipc/handlers.ts`:
- Around line 732-737: In the ipc handler in handlers.ts where you handle screen
media permission status (the branch checking if status === "not-determined"),
remove the invalid call to systemPreferences.askForMediaAccess("screen") and
simply return { success: true, granted: false, status: "not-determined" } (or
keep the existing return) so you don't invoke an unsupported Electron API;
update any adjacent comment to note that prompting for screen capture must occur
via the actual capture flow instead of askForMediaAccess.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 596320c7-b283-470c-bcbf-39208c1bf545

📥 Commits

Reviewing files that changed from the base of the PR and between 085ac2a and 44188d2.

📒 Files selected for processing (3)
  • electron-builder.json5
  • electron/ipc/handlers.ts
  • electron/main.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • electron-builder.json5

Comment thread electron/main.ts
… startup

Microphone permission is checked at startup via getMediaAccessStatus, and
camera has a dedicated request-camera-access IPC handler, but screen
recording relied entirely on desktopCapturer.getSources() to implicitly
trigger the TCC prompt — causing the permission dialog to reappear on
every launch (issue siddharthvaddem#558).

Note: askForMediaAccess() only accepts "microphone" | "camera"; screen
recording TCC is triggered via desktopCapturer.getSources() instead.

Fix:
- Import desktopCapturer in main.ts
- Call getMediaAccessStatus("screen") in app.whenReady(); trigger the
  TCC prompt via getSources when status is "not-determined"
- Add request-screen-access IPC handler symmetric to request-camera-access
com.apple.security.device.audio-input is an entitlement key and should
only appear in macos.entitlements. Placing it in extendInfo writes it
into Info.plist where it has no effect and is misleading.

The correct entry already exists in macos.entitlements; this removes
the redundant, incorrectly-placed duplicate.
@auberginewly auberginewly force-pushed the fix/electron-screen-capture-permissions branch from 44188d2 to 3dd7b85 Compare May 9, 2026 21:30
@siddharthvaddem
Copy link
Copy Markdown
Owner

is this ready for review?

@auberginewly
Copy link
Copy Markdown
Contributor Author

Yes, ready for review!

@siddharthvaddem siddharthvaddem merged commit d8da26a into siddharthvaddem:main May 9, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Screen recording permission repeatedly requested on macOS even when already granted

2 participants