Hardened Runtime verlangt eigene TCC-Entitlements
Die Ursache stand wörtlich im Protokoll von tccd: Prompting policy for hardened runtime; service: kTCCServiceCalendar requires entitlement com.apple.security.personal-information.calendars but it is missing Bei aktivierter Hardened Runtime verlangt TCC diese Entitlements auch ohne App-Sandbox. Die verbreitete Annahme, sie gälten nur für sandboxed Apps, ist falsch — und ich bin ihr aufgesessen. Ohne sie zeigt macOS den Dialog gar nicht erst an: die Anfrage kommt nach Millisekunden mit false zurück, der Status bleibt notDetermined, und die App taucht in den Systemeinstellungen nie auf. Dort lässt sich auch nichts nachtragen, der Kalenderbereich hat kein Pluszeichen — eine Sackgasse ohne jede Fehlermeldung. Gesetzt sind jetzt calendars, location, apple-events und audio-input, also alles, was Phase 3, 4 und 7 brauchen. Sie fehlen sonst genau dann, wenn das Feature fertig ist und niemand mehr an TCC denkt. Gefunden durch Ausschluss, nicht durch Nachdenken: eine minimale Test-App (normales Fenster, im Vordergrund, gleiches Zertifikat, nichts von Onyx darin) scheiterte identisch. Damit war belegt, dass es nicht an Onyx lag. Der Weg dorthin führte über mehrere falsche Fährten, die in docs/spikes/E-tcc-hardened-runtime.md stehen, damit sie niemand zweimal geht — darunter eine eigene: `log show` wurde von zsh abgefangen, und weil stderr umgeleitet war, sah die leere Ausgabe wie ein Befund aus. In der Praxis geprüft: Dialog erscheint, Zugriff erteilt, Status 3.
This commit is contained in:
@@ -23,5 +23,39 @@
|
|||||||
der Host mit Team-Zertifikat. Ohne das wird es nicht geladen. -->
|
der Host mit Team-Zertifikat. Ohne das wird es nicht geladen. -->
|
||||||
<key>com.apple.security.cs.disable-library-validation</key>
|
<key>com.apple.security.cs.disable-library-validation</key>
|
||||||
<true/>
|
<true/>
|
||||||
|
|
||||||
|
<!-- Bei aktivierter Hardened Runtime verlangt TCC diese Entitlements —
|
||||||
|
auch ohne Sandbox. Das ist die verbreitete Fehlannahme: sie gelten
|
||||||
|
nicht nur für sandboxed Apps.
|
||||||
|
|
||||||
|
Fehlt eine davon, weigert sich macOS, den Berechtigungsdialog
|
||||||
|
überhaupt anzuzeigen. Die Anfrage kommt kommentarlos mit `false`
|
||||||
|
zurück, der Status bleibt `notDetermined`, und die App taucht in den
|
||||||
|
Systemeinstellungen nie auf — dort lässt sich auch nichts von Hand
|
||||||
|
nachtragen. Der Grund steht ausschließlich im Protokoll von tccd:
|
||||||
|
|
||||||
|
"Prompting policy for hardened runtime; service: kTCCServiceCalendar
|
||||||
|
requires entitlement com.apple.security.personal-information.calendars
|
||||||
|
but it is missing"
|
||||||
|
|
||||||
|
Nachgemessen mit einer minimalen Test-App: ohne die Entitlement kein
|
||||||
|
Dialog, mit ihr sofort. -->
|
||||||
|
|
||||||
|
<!-- Kalender-Widget (Phase 3) -->
|
||||||
|
<key>com.apple.security.personal-information.calendars</key>
|
||||||
|
<true/>
|
||||||
|
|
||||||
|
<!-- Wetter am aktuellen Standort (Phase 3) -->
|
||||||
|
<key>com.apple.security.personal-information.location</key>
|
||||||
|
<true/>
|
||||||
|
|
||||||
|
<!-- AppleScript-Rückfall für Spotify und Musik (Phase 4) -->
|
||||||
|
<key>com.apple.security.automation.apple-events</key>
|
||||||
|
<true/>
|
||||||
|
|
||||||
|
<!-- Per-App-Lautstärke über Core-Audio-Taps (Phase 7). Aufgezeichnet wird
|
||||||
|
nichts; die Berechtigung heißt nur so. -->
|
||||||
|
<key>com.apple.security.device.audio-input</key>
|
||||||
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
73
docs/spikes/E-tcc-hardened-runtime.md
Normal file
73
docs/spikes/E-tcc-hardened-runtime.md
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
# Hardened Runtime verlangt eigene TCC-Entitlements
|
||||||
|
|
||||||
|
Aufgetreten am 10.08.2026 beim Kalender-Widget. Aufwendig zu finden, in einer
|
||||||
|
Zeile zu beheben — deshalb hier festgehalten, bevor es bei Standort, Apple
|
||||||
|
Events und Audio erneut zuschlägt.
|
||||||
|
|
||||||
|
## Erscheinungsbild
|
||||||
|
|
||||||
|
`EKEventStore.requestFullAccessToEvents()` kehrt nach wenigen Millisekunden mit
|
||||||
|
`false` zurück. Kein Fehler, kein Dialog. `authorizationStatus` bleibt auf
|
||||||
|
`notDetermined`. In den Systemeinstellungen taucht die App **gar nicht** auf —
|
||||||
|
und dort lässt sich auch nichts von Hand nachtragen, denn der Kalenderbereich
|
||||||
|
hat kein Pluszeichen. Einträge entstehen ausschließlich durch eine erfolgreiche
|
||||||
|
Anfrage. Man sitzt also in einer Sackgasse ohne jede Fehlermeldung.
|
||||||
|
|
||||||
|
## Ursache
|
||||||
|
|
||||||
|
```
|
||||||
|
tccd: Prompting policy for hardened runtime; service: kTCCServiceCalendar
|
||||||
|
requires entitlement com.apple.security.personal-information.calendars
|
||||||
|
but it is missing
|
||||||
|
```
|
||||||
|
|
||||||
|
Bei aktivierter Hardened Runtime verlangt TCC diese Entitlements — **auch ohne
|
||||||
|
App-Sandbox.** Die verbreitete Annahme, sie gälten nur für sandboxed Apps, ist
|
||||||
|
falsch. Ohne sie zeigt macOS den Dialog nicht einmal an.
|
||||||
|
|
||||||
|
## Behebung
|
||||||
|
|
||||||
|
In `Onyx.entitlements`, je nach genutztem Dienst:
|
||||||
|
|
||||||
|
| Dienst | Entitlement |
|
||||||
|
|---|---|
|
||||||
|
| Kalender | `com.apple.security.personal-information.calendars` |
|
||||||
|
| Standort | `com.apple.security.personal-information.location` |
|
||||||
|
| Apple Events (AppleScript) | `com.apple.security.automation.apple-events` |
|
||||||
|
| Audioaufnahme / Process Taps | `com.apple.security.device.audio-input` |
|
||||||
|
| Kontakte | `com.apple.security.personal-information.addressbook` |
|
||||||
|
|
||||||
|
## Wie es gefunden wurde
|
||||||
|
|
||||||
|
Nicht durch Nachdenken, sondern durch Ausschluss. Entscheidend war eine
|
||||||
|
**minimale Test-App**: normales Fenster, im Vordergrund, gleiches Zertifikat,
|
||||||
|
nichts von Onyx darin — und sie scheiterte identisch. Damit war belegt, dass es
|
||||||
|
nicht an Onyx lag, und die Suche konnte sich auf die Umgebung verlagern.
|
||||||
|
|
||||||
|
Der Weg dorthin führte über mehrere falsche Fährten, die hier stehen, damit sie
|
||||||
|
niemand zweimal geht:
|
||||||
|
|
||||||
|
- **`log show` wurde von zsh abgefangen** („too many arguments"). Weil stderr
|
||||||
|
umgeleitet war, sah die leere Ausgabe wie ein Befund aus. `/usr/bin/log`
|
||||||
|
benutzen.
|
||||||
|
- **`promptPolicy = 0`** im Protokoll gehörte zu `kTCCServiceReminders`, nicht
|
||||||
|
zum Kalender. Der bekam durchgehend `promptPolicy = 4`.
|
||||||
|
- **Bildschirmzeit** stand unter Verdacht (ein `digital_health_restrictions`-Profil
|
||||||
|
ist installiert), schränkt aber nur Game Center und die Zeitsynchronisation ein.
|
||||||
|
- **Ein verklemmter TCC-Eintrag** existierte tatsächlich und wurde mit
|
||||||
|
`tccutil reset Calendar <bundle-id>` entfernt — behob das Problem aber nicht.
|
||||||
|
|
||||||
|
Zwei Nebenbefunde, die für sich schon Fehler waren und mitbehoben wurden:
|
||||||
|
|
||||||
|
- **`ENABLE_DEBUG_DYLIB`** (Xcodes Voreinstellung im Debug-Build) lagert den
|
||||||
|
Programmcode in eine eigene dylib aus. Das Hauptprogramm ist dann nur ein
|
||||||
|
Rumpf, und die TCC-Anfrage erreichte `tccd` überhaupt nicht. Steht jetzt auf `NO`.
|
||||||
|
- **SwiftUIs `Settings`-Szene** wird über den privaten Selektor
|
||||||
|
`showSettingsWindow:` geöffnet und kommt bei `.accessory`-Apps unzuverlässig
|
||||||
|
an. Onyx führt sein Einstellungsfenster deshalb selbst.
|
||||||
|
|
||||||
|
## Merksatz
|
||||||
|
|
||||||
|
Wenn ein Berechtigungsdialog ausbleibt, ohne dass irgendwo ein Fehler steht:
|
||||||
|
zuerst `/usr/bin/log show --predicate 'process == "tccd"'` lesen. Der Grund
|
||||||
|
steht dort im Klartext — und nirgendwo sonst.
|
||||||
Reference in New Issue
Block a user