fix(desktop): declare macOS Contacts and Apple Events usage strings
Signed, hardened-runtime builds without an NSContactsUsageDescription / NSAppleEventsUsageDescription in mac.extendInfo are denied Contacts and Apple Events access by TCC without ever showing a prompt — macOS requires the usage string before it will even ask (#59482). Declare both next to the sibling mic/camera/calendar strings, with a packaging test that holds the contract at the config seam so the strings can't be lost in the next config move. Fixes #59482 Co-authored-by: Shashwat Gokhe <shashwatgokhe2@gmail.com>
This commit is contained in:
@@ -163,7 +163,9 @@ module.exports = {
|
||||
NSRemindersFullAccessUsageDescription: `${displayName} needs full access to Reminders to read and manage reminders when explicitly requested.`,
|
||||
NSScreenCaptureUsageDescription: `${displayName} captures the screen when you ask the agent to screenshot or record it.`,
|
||||
NSLocalNetworkUsageDescription: `${displayName} connects to devices on your local network when a plugin or feature you enable requests it.`,
|
||||
NSAppleMusicUsageDescription: `${displayName} accesses your music library when a plugin or feature you enable requests it.`
|
||||
NSAppleMusicUsageDescription: `${displayName} accesses your music library when a plugin or feature you enable requests it.`,
|
||||
NSContactsUsageDescription: `${displayName} uses Contacts access when you ask it to read or update your address book.`,
|
||||
NSAppleEventsUsageDescription: `${displayName} uses Apple Events to automate apps you explicitly ask it to control.`
|
||||
},
|
||||
target: ['dmg', 'zip'],
|
||||
sign: createMacSigner({
|
||||
|
||||
31
apps/desktop/electron/mac-usage-strings.test.ts
Normal file
31
apps/desktop/electron/mac-usage-strings.test.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
// TCC usage strings live in electron-builder.config.cjs's mac.extendInfo —
|
||||
// without them a hardened-runtime (signed) build is denied Contacts / Apple
|
||||
// Events access silently: macOS requires the usage description BEFORE it will
|
||||
// even show the permission prompt (#59482). These tests hold that contract at
|
||||
// the packaging seam so the strings can't silently disappear in a config move
|
||||
// again (they were lost once already when the builder config moved out of
|
||||
// package.json).
|
||||
import assert from 'node:assert/strict'
|
||||
import { createRequire } from 'node:module'
|
||||
|
||||
import { test } from 'vitest'
|
||||
|
||||
const require: NodeJS.Require = createRequire(import.meta.url)
|
||||
|
||||
const MAC_USAGE_STRINGS: readonly [string, string][] = [
|
||||
['NSContactsUsageDescription', 'Contacts'],
|
||||
['NSAppleEventsUsageDescription', 'Apple Events']
|
||||
]
|
||||
|
||||
test('mac extendInfo declares a usage string for every TCC-gated desktop service', () => {
|
||||
const config = require('../electron-builder.config.cjs')
|
||||
const extendInfo = config?.mac?.extendInfo
|
||||
|
||||
assert.ok(extendInfo, 'electron-builder.config.cjs must define mac.extendInfo')
|
||||
|
||||
for (const [key, service] of MAC_USAGE_STRINGS) {
|
||||
const value = extendInfo[key]
|
||||
|
||||
assert.ok(typeof value === 'string' && value.trim().length > 0, `mac.extendInfo.${key} must be a non-empty usage string; without it macOS denies ${service} access without showing a TCC prompt (#59482)`)
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user