Opened 6 weeks ago

#74272 new defect

emacs-app: subprocesses crash with SIGABRT on TCC-gated frameworks (missing NS*UsageDescription keys)

Reported by: diekhans (Mark Diekhans) Owned by:
Priority: Normal Milestone:
Component: ports Version:
Keywords: haspatch Cc: drkp (Dan Ports)
Port: emacs-app

Description

## Description

Emacs.app as built by the emacs-app subport declares usage-description keys only for the file-access TCC services and Apple Events:

$ plutil -p /Applications/MacPorts/Emacs.app/Contents/Info.plist | grep UsageDescription
  "NSAppleEventsUsageDescription"       => "Emacs requires permission to send AppleEvents to other applications."
  "NSDesktopFolderUsageDescription"     => "Emacs requires permission to access the Desktop folder."
  "NSDocumentsFolderUsageDescription"   => "Emacs requires permission to access the Documents folder."
  "NSDownloadsFolderUsageDescription"   => "Emacs requires permission to access the Downloads folder."
  "NSRemovableVolumesUsageDescription"  => "Emacs requires permission to access files on Removable Volumes."

None of the class-based services (Photos, Camera, Microphone, Contacts, Calendars, Reminders, Location, Speech Recognition, Bluetooth) are declared.

macOS TCC attributes a privacy check to the responsible process found by walking up the parent chain. For a command-line program started from a shell hosted inside Emacs (M-x shell, eshell, vterm, M-x compile, org-babel, …) that responsible process is Emacs.app. So such a program is killed with SIGABRT instead of getting the normal permission dialog — even if its own bundle declares the required key.

### Reproduction

Build a bundle-less probe that only touches Photos.framework (full source in the linked PR):

clang -framework Photos -framework Foundation -o photo_probe photo_probe.m

Run it from a shell inside Emacs. Crash report:

procName        => photo_probe
parentProc      => bash
responsibleProc => Emacs
coalitionName   => org.gnu.Emacs
exception       => EXC_CRASH / SIGABRT      (shell reports exit 134)
termination     => namespace TCC, code 0:
    "This app has crashed because it attempted to access privacy-sensitive data without a
     usage description. The app's Info.plist must contain an NSPhotoLibraryUsageDescription
     key with a string value explaining to the user how the app uses this data."

Run from iTerm2 directly: works as expected.

This was originally hit running osxphotos/PyObjC scripts from a shell inside Emacs, but it is not Python-specific.

### Environment

  • macOS 26.5.2 (25F84), Mac16,11 (Apple M4 Pro)
  • emacs-app @30.2_14+nativecomp+rsvg+treesitter
  • GNU Emacs 30.2 (build 2, aarch64-apple-darwin25.5.0, NS appkit-2685.60)

### Notes

Terminal.app is not a counterexample — it declares zero usage descriptions and relies on the Apple-private entitlement com.apple.private.tcc.allow-prompting = [kTCCServiceAll], which third-party apps cannot use. iTerm2 3.6.8 is the applicable precedent: it declares 14 such keys.

Declaring a usage description does not grant access; it only allows macOS to prompt instead of aborting.

### Fix

Pull request extends the existing files/patch-Info.plist.in.diff with 14 missing class-based keys, skipping the ones upstream already declares (NSAppleEvents*, the *Folder* and *RemovableVolumes* keys in both trees, plus NSSpeechRecognition* which emacs master has already added). Verified to apply with zero fuzz against both the 30.2 tarball and the emacs-master snapshot used by emacs-app-devel, with no duplicate keys in either.

Also being reported upstream to GNU Emacs, since nextstep/templates/Info.plist.in lives in the Emacs source tree.

Prepared with the assistance of claude-code.

Change History (0)

Note: See TracTickets for help on using tickets.