
Deine Mac-App erteilt Mikrofonzugriff — und vergisst ihn bei jedem Start
GeekBye hat um Mikrofonzugriff gebeten, du hast ihn erteilt, und es hat funktioniert. Beim nächsten Start: weg. Und die App tauchte in den Systemeinstellungen → Mikrofon nie überhaupt auf. Schuld war eine Sicherheitsfunktion von macOS, die die App still aus einem Pfad ausführte, der sich in Luft auflöst — hier ist die Diagnose und der Ein-Klick-Fix.
Hier ist ein Bug, der dich an deinen eigenen Augen zweifeln lässt. Du installierst GeekBye, es bittet um Mikrofonzugriff, du klickst auf Erlauben, und die Transkription funktioniert. Super. Du beendest es, öffnest es am nächsten Morgen wieder — und es bittet erneut um Mikrofonzugriff. Du gehst in die Systemeinstellungen → Datenschutz & Sicherheit → Mikrofon, um es von Hand zu korrigieren, und GeekBye steht nicht einmal in der Liste. Nicht verweigert. Nicht erlaubt. Einfach abwesend, als hätte es nie gefragt.
Jedes einzelne Teil sah für sich genommen korrekt aus. Der Dialog war echt. Die Berechtigung funktionierte im Moment. Die App war korrekt signiert und notarisiert, mit den richtigen Verwendungstexten. Und trotzdem verdampfte die Berechtigung bei jedem Start. GeekBye v2.0.6 hat es behoben — und die Grundursache ist eines der hinterlistigsten Dinge, die macOS tut, um dich zu schützen.
Die Funktion, die die App vor sich selbst versteckte
Schuld ist macOS App Translocation, eine Sicherheitsfunktion von Gatekeeper. Wenn du eine App herunterlädst und sie direkt aus dem DMG oder aus deinem ~/Downloads-Ordner startest — überall dort, wo sie noch „unter Quarantäne" steht — führt macOS sie nicht wirklich von der Stelle aus, an der du sie siehst. Es kopiert sie transparent an einen zufälligen, schreibgeschützten Pfad tief unter /private/var/folders/.../AppTranslocation/… und führt diese Kopie aus. Das ist eine gute Abwehr: Sie verhindert, dass ein bösartiger Download an den Dateien neben sich herummanipuliert.
Aber hier ist der Zusammenstoß. Das Berechtigungssystem von macOS (TCC — das Ding, das nachverfolgt, wer dein Mikrofon, deine Kamera, deinen Bildschirm nutzen darf) identifiziert eine App anhand ihres Pfads und ihrer Code-Identität. Wenn die App transloziert wird, ist dieser Pfad zufällig und temporär. Wenn du also Mikrofonzugriff erteilst, protokolliert macOS die Berechtigung pflichtbewusst — gegen einen Pfad, der beim nächsten Start nicht existieren wird. Du öffnest die App erneut, macOS transloziert sie an einen anderen zufälligen Pfad, sieht eine App, über die es keinen Eintrag hat, und fragt erneut. Und weil dieser Phantom-Pfad nie ein stabiler Ort ist, verdient sich die App nie eine dauerhafte Zeile in den Systemeinstellungen → Mikrofon.
Die App erteilte einem Gespenst die Berechtigung.
Deshalb traf es auch nur manche. Wenn deine Kopie von GeekBye bereits in /Applications lebte — weil du sie dorthin gezogen hast oder weil sie per Auto-Update dorthin kam — gibt es keine Quarantäne, keine Translocation, einen stabilen Pfad, und alles bleibt perfekt erhalten. Der Bug war für uns und für jeden nach der ersten Installation unsichtbar, genau die Art von Bug, die am längsten überlebt.
Der Fix: der App ein echtes Zuhause geben
Da das gesamte Problem ein instabiler Pfad ist, besteht der Fix darin, die App auf einen stabilen zu bringen. v2.0.6 erkennt, wenn GeekBye transloziert läuft (oder einfach außerhalb von /Applications läuft) und bietet ein „In Programme verschieben" per Klick — mithilfe des macOS-Verschiebeaufrufs, der das Bundle nach /Applications kopiert und es von dort neu startet. Ab diesem Punkt hat die App eine feste Identität: Die Mikrofonberechtigung bleibt erhalten, die Bildschirmaufnahme bleibt erhalten, und GeekBye erscheint endlich in den Systemeinstellungen, wo man es erwarten würde.
Der Dialog ist höflich dabei. Er bietet In Programme verschieben, Jetzt nicht und Nicht mehr fragen — und er merkt sich die letzte Wahl, damit die App niemanden nervt, der einen bewussten Grund hat, sie von woanders auszuführen. Die Entscheidung, ob der Dialog überhaupt gezeigt wird, ist in kleine, reine Funktionen ausgelagert (ist dieser Build transloziert? ist er außerhalb von /Applications? hat der Nutzer ihn unterdrückt?), damit die Logik per Unit-Test geprüft werden kann, ohne einen echten notarisierten Build auf einem echten Quarantäne-Volume starten zu müssen.
Dasselbe Release vereinfachte auch die Berechtigungserfahrung selbst. GeekBye öffnete früher ein maßgeschneidertes, eigenes In-App-Berechtigungsfenster — ein paar hundert Zeilen Oberfläche, die versuchten, etwas nachzubauen, das das Betriebssystem bereits gut macht. v2.0.6 hat es gelöscht und sich auf den nativen macOS-Berechtigungsdialog gestützt, unterstützt von einem dezenten, nicht blockierenden Banner, das nur erscheint, wenn eine erforderliche Berechtigung tatsächlich fehlt. Weniger Code, und ein Verhalten, das Nutzer bereits kennen, weil jede andere Mac-App genauso funktioniert.
Der Teil, auf den ich am stolzesten bin: Wir haben es bewiesen, bevor wir es glaubten
Es wäre einfach gewesen, Translocation zu erraten und einen Fix auszuliefern. Stattdessen lieferte das Release zuerst eine Start-Diagnose: Beim Start meldet GeekBye nun seinen eigenen Pfad der ausführbaren Datei und ob es transloziert ist, ob es innerhalb von /Applications liegt, und den aktuellen Status der Mikrofon- und Bildschirmberechtigungen. Diese Telemetrie machte aus einer plausiblen Theorie eine bestätigte — Produktionsdaten zeigten, dass die betroffenen Sitzungen tatsächlich aus translozierten Pfaden außerhalb von /Applications liefen, genau wie vorhergesagt.
Diese Reihenfolge ist wichtig. „Dialog erscheint, aber Berechtigung bleibt nicht erhalten" hat mehrere mögliche Erklärungen — ein Signaturproblem, ein fehlender Verwendungstext, ein Entitlement-Problem, eine Eigenart der TCC-Datenbank. Wir schlossen die Ursachen auf API-Ebene aus (der Anfragepfad war nachweislich korrekt) und ließen dann reale Daten auf die Identitäts-/Pfad-Ebene zeigen, statt einen hoffnungsvollen Fix auszuliefern und zu hoffen, dass die Support-Tickets aufhören.
Drei Dinge, die dieser Bug lehrt
- Eine Berechtigung, die gefragt wird, aber nicht erhalten bleibt, ist ein Identitäts-Problem, kein API-Problem. Wenn der Anfragecode korrekt ist und die Berechtigung trotzdem verschwindet, hör auf, die Anfrage umzuschreiben. Frag, an welchen Pfad und welche Code-Identität das Betriebssystem die Berechtigung bindet — und ob diese Identität über Starts hinweg stabil ist.
- Liefere die Diagnose mit (oder vor) dem Fix. Ein paar Felder — von wo laufe ich, wie ist mein Berechtigungsstatus — machten aus einer fundierten Vermutung eine verifizierte Grundursache und sagten uns genau, welche Nutzer betroffen waren. Instrumentiere die Grenze, die du verdächtigst, bevor du sie patchst.
- Die Bugs, die sich vor Entwicklern verstecken, sind die, die in der „falschen" Umgebung laufen. Unserer lebte auf jeder Dev-Maschine in
/Applications, also war der Bug für uns strukturell unsichtbar, während er Erstnutzer traf. Wenn ein Bericht sich nicht reproduzieren lässt, ist die erste Frage, was an der Umgebung, in der er läuft, anders ist, nicht ob der Nutzer sich irrt.
GeekBye v2.0.6 lieferte den Verschiebe-Dialog und die Diagnose zusammen. Für den größeren Zuverlässigkeitsbogen, in den das gehört, siehe was eine Version 2 wirklich kostet (v2.0.0) und warum die Bildschirmaufnahme den falschen Monitor erfasst (v2.0.10) — ein weiterer Bug, der nur in einer bestimmten Umgebung auftauchte. Für das Release der kleinen Details nebenan, ruhige Software: der Flacker-Fix und der Antwortmodus-Chip (v2.0.3 + v2.0.5).