8 Min. Lesezeit

macOS-Prozessidentität braucht mehr als eine Team ID

Ein praxistaugliches Modell für macOS-Prozessidentitäten mit Team ID, Signing Identifier, Designated Requirements, Pfaden und strenger Behandlung unsignierter Builds.

macOS-Prozessidentität braucht mehr als eine Team ID

Eine Team ID reicht nicht aus, um zu entscheiden, welcher macOS-Prozess ein Geheimnis verwenden darf. Sie kennzeichnet ein Apple-Entwicklerteam, nicht eine bestimmte ausführbare Datei dieses Teams. Wenn Sie allein eine Team ID autorisieren, können alle passend signierten Apps, Hilfsprogramme, Testwerkzeuge und künftigen Binärdateien dieses Teams denselben Zugriff erben.

Eine belastbare Autorisierungsidentität verbindet die Signaturautorität mit dem Signing Identifier, speichert eine Requirement, die legitime Updates übersteht, und prüft diese Identität gegen den Prozess, der tatsächlich anfragt. Der Pfad zur ausführbaren Datei gehört weiterhin auf die Freigabekarte und in den Auditdatensatz, sollte aber nicht über die Autorisierung entscheiden. Unsignierte und ad-hoc-signierte Entwicklungs-Builds brauchen einen getrennten, sichtbar schwächeren Weg statt einer stillschweigenden Ausnahme.

An einer Geheimnisgrenze ist diese Unterscheidung besonders wichtig. Eine Code-Signatur kann Ihnen sagen, wer einen Prozess signiert hat und welchen Programmnamen der Signierer beansprucht. Sie kann nicht sagen, dass der Prozess ein Datenbankpasswort verdient, dass seine aktuelle Anfrage sinnvoll ist oder dass ein anderes Programm desselben Entwicklers dieselbe Freigabe erhalten sollte. Identität ist ein Eingabewert für die Autorisierung, kein Ersatz dafür.

Eine Team ID identifiziert einen Signierer, kein Programm

Die Team ID beantwortet eine nützliche, aber weit gefasste Frage: Welches Apple-Entwicklerteam hat die für diesen Code verwendete Signaturidentität ausgestellt? Bei von Apple ausgestellten Entwicklerzertifikaten macht die Requirement-Sprache die Team ID über das Feld der Organisationseinheit im Blattzertifikat sichtbar. Werkzeuge können in den Signaturdetails außerdem einen Wert TeamIdentifier ausgeben.

Führen Sie dies für die genaue ausführbare Datei aus, nicht nur für das äußere App-Bundle:

codesign -dvvv /Applications/Example.app/Contents/MacOS/Example 2>&1

Der relevante Teil der Ausgabe sieht so aus:

Executable=/Applications/Example.app/Contents/MacOS/Example
Identifier=dev.example.agent
Authority=Developer ID Application: Example Developer (A1B2C3D4E5)
Authority=Developer ID Certification Authority
Authority=Apple Root CA
TeamIdentifier=A1B2C3D4E5

Eine gültige Team ID gibt Ihnen den Umfang des Signierers. Sie schließt Binärdateien aus, die von anderen Teams signiert wurden, und verhindert damit, dass ein fremder Entwickler denselben Signing Identifier beansprucht und Ihre Prüfung besteht. Apple weist in seiner Dokumentation zu SigningIdentifier ausdrücklich darauf hin: Mehrere Signierer können einen Signing Identifier beanspruchen. Eine sichere Prüfung für nicht von Apple stammenden Code braucht deshalb zusätzlich eine TeamIdentifier-Einschränkung und eine passende Validierungskategorie.

Die Umkehrung ist die Falle. Ein Team kann viele nicht zusammenhängende Produkte und viele Komponenten eines Produkts signieren. Eine App, ihr privilegiertes Hilfsprogramm, ein Anmeldeobjekt, ein Kommandozeilentool, ein XPC-Dienst und ein internes Diagnosewerkzeug können alle dieselbe Team ID haben. Ein kompromittierter Signierdienst könnte noch eine weitere Binärdatei innerhalb dieses Signiererumfangs erzeugen. Die Teamzugehörigkeit unterscheidet diese Fälle nicht.

Darum ist Team ID == approved team für den Zugriff auf Geheimnisse zu weit gefasst. Es ähnelt der Vergabe von Zugriff an alle Beschäftigten eines Unternehmens, weil ihre Ausweise vom selben Aussteller stammen. Der Aussteller zählt, doch auch der Name auf dem Ausweis zählt.

Es gibt enge Fälle, in denen eine Team ID allein absichtlich verwendet wird. Ein Entwicklerwerkzeug könnte jeder Komponente erlauben, die vom eigenen Team des Nutzers signiert wurde, auf eine austauschbare lokale Testressource zuzugreifen. Das ist eine Vertrauensrichtlinie für ein Team, keine Prozessidentität, und der Freigabetext sollte das klar sagen. Speichern Sie sie nicht unter einem Feld namens application, um später zu vergessen, wie viel Berechtigung sie vermittelt.

Der Signing Identifier trennt Programme innerhalb eines Teams

Der Signing Identifier liefert die Programmdimension, die der Team ID fehlt. codesign gibt ihn als Identifier aus. Bei einer gebündelten App entspricht er häufig der Bundle-ID, Apple verlangt diese Gleichheit jedoch ausdrücklich nicht. Der Signierer wählt den Wert, und Kommandozeilenprogramme können Identifier tragen, ohne App-Bundles zu sein.

Die Kombination aus Team ID und Signing Identifier ergibt eine wesentlich bessere Mindestidentität:

team_id = A1B2C3D4E5
signing_identifier = dev.example.agent

Das Paar bedeutet „das Programm mit dem Namen dev.example.agent, signiert von Team A1B2C3D4E5“. Ein anderes Team kann den Identifier kopieren, aber die Team-Einschränkung nicht erfüllen. Ein anderes Programm des freigegebenen Teams sollte einen anderen Identifier haben und daher nicht übereinstimmen.

Das Wort „sollte“ trägt im letzten Satz Gewicht. Ein Team kontrolliert seine eigenen Identifier und kann einen wiederverwenden. Eine nachlässige Build-Konfiguration könnte dem eingebetteten Hilfsprogramm den Identifier der Haupt-App zuweisen. Ein böswilliger oder kompromittierter Signierer könnte den freigegebenen Wert kopieren. Das Paar grenzt die Berechtigung unter der Annahme ein, dass der Signierer sowohl seine Signaturzugangsdaten als auch seinen Identifier-Namensraum schützt.

Trotzdem ist das die übliche Grenze für eine bei Updates stabile Drittanbieteridentität auf macOS. Code-Hashes sind genauer, doch jedes legitime Release ändert sie. Zertifikat-Fingerprints eignen sich ebenfalls schlecht als Kontinuitätsanker, weil Zertifikate ablaufen und ausgetauscht werden. Team ID plus Signing Identifier drückt die Kontinuität aus, die die meisten Anwendungen brauchen: künftige Versionen dieses Programms von diesem Signierer akzeptieren, ohne den gesamten Produktkatalog des Signierers zu akzeptieren.

Prüfen Sie jede ausführbare Datei, die eine Verbindung aufbauen kann. Leiten Sie den Identifier eines Hilfsprogramms nicht von der enthaltenden App ab. Apple TN3127 verwendet eine App und ihr eingebettetes Kommandozeilentool, um denselben Punkt zu verdeutlichen: Sie teilen eine Team ID, haben aber unterschiedliche Code-Signing-Identifier. Apple bezeichnet diese Trennung als Best Practice. Wenn das Hilfsprogramm die Anfrage startet, zählt seine Identität an der Grenze.

Auch Identifier müssen Byte für Byte behandelt werden. Apples aktuelle Dokumentation zu SigningIdentifier sagt, dass beim Vergleich keine Unicode-Normalisierung erfolgt. Speichern und vergleichen Sie den von Code Signing Services zurückgegebenen Wert als undurchsichtige Zeichenfolge oder Bytefolge. Kleinschreibung, Normalisierung oder ein Neuaufbau aus CFBundleIdentifier schaffen ein zweites Identitätssystem mit anderen Regeln.

Die Designated Requirement hält die Identität über Updates stabil

Eine Designated Requirement, oft DR genannt, ist der macOS-eigene Ausdruck dafür, ob aktuell gesehener Code derselbe Code ist wie früher. Sie verbindet den Signing Identifier mit Einschränkungen für die Signaturautorität. Damit kommt sie dem Autorisierungsobjekt, das Sie brauchen, näher als jedes der beiden Felder allein.

Apple TN3127 beschreibt eine DR als die Erklärung des Codes, wie ihn eine andere Partei später wiedererkennen kann. Der praktische Test in der Technote ist ein Update: Version 1.3 sollte die für Version 1.2 gespeicherte Identität erfüllen, obwohl sich ihre Bytes geändert haben. Zugleich sollte ein anderes Produkt scheitern. Genau diese Spannung muss eine dauerhafte Freigabe für Geheimnisse auflösen.

Zeigen Sie die DR an mit:

codesign -d -r- /Applications/Example.app/Contents/MacOS/Example 2>&1

Ein Developer-ID-Ergebnis hat abhängig vom Signaturweg im Allgemeinen diese Form:

Executable=/Applications/Example.app/Contents/MacOS/Example
designated => anchor apple generic and identifier "dev.example.agent" and certificate leaf[subject.OU] = "A1B2C3D4E5"

Analysieren Sie diese Anzeigezeichenfolge nicht in selbst entwickelte Felder und versuchen Sie dann nicht, Apples Auswertung nachzubauen. TN3125 warnt davor, dass sich Signaturstrukturen ändern, und verweist Entwickler für die Validierung auf codesign oder Code Signing Services. Verwenden Sie SecCodeCopyDesignatedRequirement, um eine Requirement zu erhalten, und SecCodeCheckValidity oder die APIs für Prozess-Requirements, um Code auszuwerten. Lassen Sie die Plattform ihre eigene Requirement-Form kompilieren und vergleichen.

Daraus folgt ein wichtiger Punkt: Die eigene DR des Codes ist eine Behauptung, keine Autorisierungsentscheidung. Der Signierer kann eine explizite DR liefern, und Code Signing Services kann eine erzeugen, wenn keine eingebettet ist. Ihr System entscheidet weiterhin, welche Requirement gespeichert wird und ob ihr Umfang zur Freigabe passt. Eine DR auszulesen und „vertrauenswürdig“ zu verkünden, verwechselt Identitätsmaterial mit Richtlinie.

Für gewöhnliche Developer-ID-Software ist es ein solider Standard, die bei der Freigabe validierte DR zu speichern. Bewahren Sie außerdem die angezeigte Team ID und den Signing Identifier als Auditfelder auf, damit ein Mensch die Entscheidung nachvollziehen kann. Werten Sie bei späteren Aufrufen den Live-Prozess gegen die gespeicherte Requirement aus, statt eine frisch ausgegebene DR-Zeichenfolge auf textliche Gleichheit zu vergleichen. Requirement-Objekte beschreiben Verhalten, gleichwertige Ausdrücke brauchen nicht dieselbe Formatierung.

Änderungen des Distributionswegs müssen bewusst behandelt werden. TN3127 weist darauf hin, dass Standard-DRs für Varianten aus dem Mac App Store und mit Developer ID nicht automatisch kompatibel sind, während Xcode mit benutzerdefinierten Requirements beabsichtigte Distributionsformen überbrücken kann. Weiten Sie Ihren Prüfer nicht spontan aus, wenn ein Release den Kanal wechselt. Behandeln Sie die neue Requirement als Identitätsänderung, zeigen Sie sie dem Nutzer und verlangen Sie eine neue Freigabe, sofern Sie keine ausdrückliche Kompatibilitäts-Requirement entworfen und getestet haben.

Pfade ausführbarer Dateien liefern Kontext, keinen Beweis

Ein Pfad zu einer ausführbaren Datei sagt dem Betreiber, wo macOS das Image gefunden hat. Das ist ausgezeichneter Kontext für eine Freigabe und schwache Evidenz für Kontinuität. Dateien werden verschoben, App-Translocation kann Orte verändern, Nutzer behalten mehrere Versionen und Paketmanager installieren versionierte Pfade. Umgekehrt kann ein Angreifer, der eine Datei an einem freigegebenen, beschreibbaren Pfad ersetzen kann, eine rein pfadbasierte Freigabe erben.

Die bekannte Pfad-Allowlist scheitert in beide Richtungen. Sie lehnt dasselbe signierte Programm nach einer harmlosen Verschiebung ab und akzeptiert andere Bytes nach einem böswilligen Austausch. Prüfungen von Eigentümer und Modus verringern einige Risiken beim Ersetzen, machen aus einem Pfadnamen aber keine kryptografische Identität.

Behalten Sie den Pfad für drei Aufgaben:

  • Zeigen Sie dem Nutzer, welche Installation die Anfrage ausgelöst hat.
  • Halten Sie genug Kontext fest, um einen überraschenden Aufruf zu untersuchen.
  • Wenden Sie nach erfolgreicher Signaturidentität optional eine Standortbeschränkung an.

Die letzte Verwendung kann in verwalteten Umgebungen sinnvoll sein. Sie können eine freigegebene DR verlangen und zusätzlich fordern, dass die ausführbare Datei unter einem Deployment-Verzeichnis läuft, das root gehört. Der Pfad begrenzt dann, wo ein bereits identifiziertes Programm laufen darf. Er repariert niemals eine fehlende oder ungültige Signatur.

Lösen Sie die ausführbare Datei auf und speichern Sie sie, die tatsächlich mit dem laufenden Prozess verbunden ist. Vertrauen Sie keiner vom Client gelieferten Zeichenfolge wie argv[0], einem Arbeitsverzeichnis, einem Bundle-Pfad in einer Anfrage oder einer Umgebungsvariable. Das sind Aussagen des Anfragenden. Selbst ein kanonischer Pfad kann in einen Wettlauf geraten, wenn Sie eine Datei prüfen und später einen Prozess allein anhand des gespeicherten Namens autorisieren.

Wenn die Plattform sie bereitstellt, bewahre ich sowohl den ursprünglich beobachteten als auch einen aufgelösten Pfad in den Auditdaten auf, weil Symlinks und Start-Wrapper viele Überraschungen erklären. Keiner dieser Werte gehört zum dauerhaften Identitätstupel. Entscheidet sich eine Organisation für eine Pfadbeschränkung, speichern Sie sie in einem eigenen Feld location_constraint, damit Prüfer erkennen, dass es sich um eine Richtlinie zusätzlich zur Identität handelt.

Den Live-Aufrufer statt eines Pfadnamens auswerten

Berechtigung mit dem Prozess beenden
Die Sitzungsfreigabe gilt nur, bis dieser Agentenlauf endet. Danach wird der Zugriff geschlossen.

Die Autorisierungsprüfung muss an den Prozess gebunden sein, der die Verbindung herstellt. Eine Datei bei der Installation zu prüfen, ihren Pfad zu speichern und später allem zu vertrauen, was dort läuft, lässt eine Lücke zwischen Prüfung und Nutzung. Selbst die aktuelle Datei unter diesem Pfad nach Eingang einer Anfrage zu prüfen, kann einen Ersatz untersuchen statt das bereits laufende Image.

macOS Code Signing Services unterscheidet zwischen statischem Code auf dem Datenträger und dynamischem Code, der einem laufenden Prozess zugeordnet ist. Apple dokumentiert SecCodeCopyGuestWithAttributes, um ein Codeobjekt für Gastcode zu erhalten, häufig über die PID, und SecCodeCheckValidityWithProcessRequirement, um einen laufenden Prozess gegen eine Requirement zu prüfen. Die neuere Lightweight-Requirement-API kann die gewünschten Einschränkungen für TeamIdentifier und SigningIdentifier ausdrücklich machen. Verwenden Sie die für Ihr Deployment-Ziel unterstützte API, statt in der Produktion die Ausgabe von codesign auszuwerten.

Ein zuverlässiger Verbindungsablauf sieht so aus:

  1. Ermitteln Sie die vom Kernel bereitgestellte Prozessidentität an der IPC-Grenze, etwa das Audit-Token einer akzeptierten Verbindung. Akzeptieren Sie keine in der Anfrage übermittelte PID.
  2. Lösen Sie diesen Live-Prozess zu einem dynamischen Codeobjekt auf und validieren Sie seine Signatur mit der Plattform-API.
  3. Werten Sie die gespeicherte Requirement oder die gespeicherten Einschränkungen für Signierer und Identifier gegen dasselbe Codeobjekt aus.
  4. Erfassen Sie Pfad, PID, Prozessstartidentität, sofern vorhanden, Signaturdaten und Validierungsergebnis im Entscheidungsdatensatz.
  5. Binden Sie die Freigabe an die Verbindung oder Prozesslaufzeit und verwerfen Sie sie, wenn diese Laufzeit endet.

Eine bloße PID ist kein dauerhafter Handle, weil der Kernel Prozess-IDs wiederverwendet. Liest der Prüfer eine PID, wartet und schlägt sie später erneut nach, kann er einen anderen Prozess untersuchen. Ein Audit-Token enthält mehr Prozessidentität als eine vom Client gelieferte Ganzzahl, und eine verbindungsgebundene Prüfung verkleinert das Zeitfenster. Die genaue API hängt davon ab, ob Ihre Grenze XPC, ein Unix-Domain-Socket oder ein anderer IPC-Mechanismus ist. Die Regel bleibt gleich: Leiten Sie das Subjekt aus der Sicht des Betriebssystems auf den Kommunikationspartner ab.

Validieren Sie vor der Anzeige der Identität. Sonst kann eine Freigabekarte Felder aus einer fehlerhaften oder ungültigen Signatur zeigen, als hätte macOS für sie gebürgt. Die Karte sollte gültige Developer-ID-Signatur klar von Identifier-Text war vorhanden unterscheiden. Schlägt die Validierung fehl, fallen Sie unter derselben Freigabe nicht auf einen Pfadvergleich zurück.

Prozessbäume brauchen eine ausdrückliche Entscheidung. Wenn ein signierter Agent /bin/sh startet und die Shell direkt verbindet, ist die Shell der Kommunikationspartner. Automatisch zu einem Vorfahren zu laufen und dessen Identität zu leihen, kann ersetzte Kinder oder nicht zusammenhängende Nachkommen autorisieren. Soll Ihre Architektur den Starter autorisieren, binden Sie eine Capability an die ursprünglich authentifizierte Verbindung und reichen Sie sie über einen kontrollierten Kanal weiter. Ermitteln Sie Absicht nicht erneut durch Hochlaufen über Eltern-PIDs.

Darum sollte eine Autorisierung auch ablaufen, wenn der freigegebene Prozess endet. Eine gespeicherte Identität kann künftige Freigaben unterstützen, doch eine Sitzungsfreigabe sollte nicht losgelöst weiterbestehen und sich dauerhaft an jeden passenden Prozess heften. Trennen Sie „wir erkennen dieses Programm“ von „dieser Lauf ist jetzt freigegeben“.

Unsignierte und ad-hoc-Builds brauchen eine eigene Richtlinie

Unsignierter Code hat keine Designated Requirement. Ad-hoc-signierter Code hat eine DR, die an genau diese Codeversion gebunden ist, sodass ein Neubau die Identität verändert. Apple TN3127 sagt, dass macOS beide Formen nicht zuverlässig versionsübergreifend verfolgen kann. Ein Secret-Broker sollte diese Grenze erhalten, statt sie mit einer Verzeichnisausnahme zu überdecken.

Für Produktionsgeheimnisse sollten Sie den Zugriff verweigern, wenn dem Aufrufer eine gültige, über Updates stabile Signatur fehlt. Das ist die sauberste Regel und am leichtesten zu erklären. Entwickler können lokale Builds mit einer Apple-Development-Identität oder einer privaten Signaturidentität signieren, deren Vertrauen und Requirements die Organisation verwaltet. Diese Unbequemlichkeit ist meist kleiner als die Unklarheit einer dauerhaften Ausnahme für unsignierten Code.

Lokale Entwicklung braucht manchmal einen schwächeren Modus. Machen Sie ihn optional, nennen Sie ihn development approval und begrenzen Sie seinen Wirkungsbereich. Ein vernünftiges Design bindet die Freigabe an die aktuelle Prozesslaufzeit und den exakten Code-Hash, zeigt unsigned oder ad hoc deutlich, schließt Produktionsgeheimnisse aus und fragt nach jedem Neubau erneut. Die wiederholte Abfrage ist kein Fehler. Sie spiegelt wider, dass die ausführbare Datei keine Kontinuität mehr hat, die macOS belegen kann.

Verwenden Sie nicht diese beliebten Ersatzlösungen:

  • Einen Pfad im Home-Verzeichnis des Nutzers, weil derselbe Nutzer ihn ersetzen kann.
  • Einen Dateinamen oder eine Bundle-ID aus Metadaten, weil unsignierter Code jeden beliebigen Wert beanspruchen kann.
  • Die Signatur des Elternprozesses, weil das Kind der Kommunikationspartner ist, der die Berechtigung nutzt.
  • Eine pauschale Terminalfreigabe, weil Terminals beliebige Programme starten.
  • Einen Hash als dauerhafte Identität, weil jeder legitime Neubau eine manuelle Migration verlangt.

Ein Hash kann eine zeitlich begrenzte Ausnahme sicher eingrenzen. Er sagt „genau diese Bytes für diesen Lauf“, nicht „dies ist nach einem Update dasselbe Programm“. Halten Sie diesen semantischen Unterschied in Speicherung und Benutzeroberfläche sichtbar.

Behandeln Sie eine fehlende Team ID als Zustand zur Klassifizierung, nicht als Nullwert, der einen Vergleich umgeht. Von Apple signierter Plattformcode, unabhängig signierter Code, Ad-hoc-Code und unsignierter Code passen nicht alle in dasselbe Tupel. Definieren Sie, welche Kategorien Ihr Produkt akzeptiert, und testen Sie jede Kategorie. Eine Prüfung if team != expected mit einem nachgiebigen Zweig für leere Werte hat genug Autorisierungsfehler verursacht, dass sie einen eigenen Unit-Test verdient.

Einen Identitätsdatensatz speichern, der seinen Umfang selbst erklärt

Geheimnisübergaben durch Aktionen ersetzen
Sallyport fügt Anmeldedaten selbst ein und gibt dem berechtigten Agentenprozess nur das Ergebnis zurück.

Ein dauerhafter Datensatz sollte die maschinell auswertbare Requirement, die für Menschen lesbaren Signaturdaten, die Codekategorie und jede separat freigegebene Standortbedingung bewahren. Er sollte auch den Umfang der Freigabe erfassen. Wer die Datenbank sechs Monate später prüft, muss erkennen können, ob die Freigabe einen Lauf, künftige signierte Versionen oder jedes Programm eines Teams umfasste.

Dieses Beispiel verwendet Platzhalterwerte und ein als Base64 dargestelltes serialisiertes Requirement-Blob. Das Blob sollte von Code Signing Services stammen, nicht aus dem Kompilieren einer vom Client gelieferten Zeichenfolge:

{
  "schema": 1,
  "code_category": "developer_id",
  "team_id": "A1B2C3D4E5",
  "signing_identifier": "dev.example.agent",
  "designated_requirement": "BASE64_PLATFORM_REQUIREMENT",
  "approval_scope": "matching_identity_per_session",
  "location_constraint": null,
  "observed_path": "/Applications/Example.app/Contents/MacOS/Example"
}

Der Abgleichalgorithmus sollte langweilig sein. Klassifizieren und validieren Sie zuerst die Live-Signatur des Aufrufers. Werten Sie bei einer signierten Identität die gespeicherte Requirement gegen diesen Live-Prozess aus. Bestätigen Sie, dass die zurückgegebenen Team ID und Signing Identifier mit den Auditfeldern übereinstimmen. Eine Abweichung weist auf beschädigten Zustand oder einen Fehler hin, nicht auf einen Grund, den Zugriff auszuweiten. Wenden Sie anschließend eine mögliche Standortbeschränkung an. Ziehen Sie zuletzt den Freigabeumfang und etwaige Anforderungen pro Geheimnis heran.

Pseudocode erleichtert die Prüfung des Fehlerverhaltens:

caller = peer_from_kernel(connection)
code = dynamic_code(caller)
result = validate(code)

if result.category not in accepted_categories:
    deny("unsupported code category")

identity = evaluate(stored_requirement, code)
if identity != satisfied:
    deny("process identity changed")

if facts(code) != stored_audit_facts:
    deny("identity record inconsistent")

if location_constraint and not location_allowed(code, location_constraint):
    deny("approved program ran from an unapproved location")

authorize_for(connection_lifetime, requested_secret)

Beachten Sie, was der Algorithmus nicht tut. Er akzeptiert keine Team ID allein, vergleicht keinen Pfad vor der Signaturprüfung, durchsucht keine Elternprozesse nach einer günstigeren Identität und wandelt einen unsignierten Aufrufer nicht stillschweigend in eine Entwicklungsfreigabe um. Jeder Fehler erzeugt einen Grund, den Nutzer und Prüfer verstehen können.

Planen Sie Identitätsmigration als Vorgang, nicht als Ausnahme. Ein Teamtransfer, eine Änderung des Signing Identifiers, ein Wechsel des Distributionskanals oder der Umstieg von Ad-hoc- auf Developer-ID-Signierung kann die Requirement legitim verändern. Zeigen Sie die alten und neuen Daten nebeneinander, verlangen Sie die Freigabe durch eine berechtigte Person und behalten Sie beide Datensätze im Auditverlauf. Überschreiben Sie nie die alte Identität, sodass frühere Aufrufe scheinbar von der neuen stammen.

Testen Sie mit gegnerischen Testdaten. Signieren Sie zwei ausführbare Dateien mit demselben Team und unterschiedlichen Identifiern, nur eine darf bestehen. Signieren Sie eine weitere mit dem freigegebenen Identifier unter einem anderen Team, sie muss scheitern. Kopieren Sie die freigegebene ausführbare Datei an einen neuen Pfad, die Identität sollte bestehen, sofern keine Standortbedingung etwas anderes sagt. Ersetzen Sie die Datei nach dem Start und bestätigen Sie, dass der Prüfer den Live-Kommunikationspartner bewertet. Bauen Sie ein Ad-hoc-Target neu und bestätigen Sie, dass dessen temporäre Freigabe nicht erhalten bleibt.

Identität kann nicht beantworten, ob die Aktion erlaubt ist

Agentenanfragen durch ein Tor leiten
Der Shim `sp mcp` leitet die HTTP- und SSH-Aktionen eines MCP-Agenten durch Sallyport.

Eine korrekte Prozessübereinstimmung identifiziert nur das Subjekt einer Anfrage. Sie belegt nicht, dass das Subjekt jedes Geheimnis nutzen, jeden Host aufrufen oder den Zugriff dauerhaft behalten darf. Halten Sie Prozessidentität, Sitzungsfreigabe und Aktionsfreigabe als getrennte Entscheidungen, selbst wenn eine Oberfläche sie gemeinsam zeigt.

Diese Trennung verhindert eine häufige Ausweitung von Berechtigungen. Ein Nutzer gibt einem signierten Programmieragenten den Zugriff auf ein Entwicklungstoken, das System speichert die Agentenidentität, und eine spätere Implementierung behandelt diesen Datensatz als Freigabe für sämtliche Zugangsdaten. Weder Team ID noch Signing Identifier oder DR enthalten die ursprüngliche Ressourcengrenze. Die Identität blieb stabil, während die Autorisierung stillschweigend ausgeweitet wurde.

Machen Sie das Autorisierungstupel ausdrücklich: Subjekt, Aktion, Ressource, Bedingungen und Laufzeit. Für ein Secret-Gateway könnte es so aussehen:

subject: requirement R42 satisfied by this live process
action: perform an HTTP request with injected bearer credentials
resource: issue-tracker-development
conditions: vault unlocked and session approved
lifetime: this connection, with per-call approval if the secret requires it

Das Feld für das Subjekt verweist auf den Prozessidentitätsdatensatz. Die übrigen Felder stammen aus der angefragten Operation und den sie umgebenden Kontrollen. Diese Struktur unterstützt auch einen Agenten, der sowohl HTTP als auch SSH verwendet, ohne vorzutäuschen, dass Prozesswiedererkennung beide Kanäle automatisch autorisiert.

Entitlements können eine spezialisierte Richtlinie informieren, sollten aber nicht zu einem improvisierten Vertrauenswert werden. Ein Entitlement ist eine signierte Behauptung, die macOS für bestimmte Systemfunktionen auslegt. Sein Vorhandensein bedeutet nicht, dass das Programm allgemein sicherer ist, und sein Fehlen schwächt keine Übereinstimmung von Team ID plus Identifier. Prüfen Sie ein bestimmtes Entitlement nur, wenn Ihr Autorisierungsdesign ihm eine präzise Bedeutung zuweist.

Auch Notarisierung und Gatekeeper beantworten andere Fragen. Ihre Akzeptanz kann zur Validierung der Codekategorie und zum Vertrauensniveau des Distributionswegs beitragen, doch keines von beiden identifiziert ein einzelnes Programm innerhalb eines Entwicklerteams oder gewährt Zugriff auf Ihr Geheimnis. spctl -a -vv -t exec während der Diagnose kann erklären, ob Gatekeeper eine Datei akzeptiert. Ersetzen Sie Ihre gespeicherte Requirement-Prüfung nicht durch dieses Urteil.

Widerruf braucht dieselbe Präzision. Der Widerruf einer Sitzung sollte die aktuelle Verbindung stoppen, ohne die erkannte Programmidentität zu löschen. Der Widerruf einer Identität sollte passende künftige Prozesse wieder durch die Freigabe führen. Der Widerruf einer Ressourcenfreigabe sollte andere Freigaben unberührt lassen. Wenn ein einzelnes Boolean namens trusted alle drei steuert, kann das Datenmodell die tatsächliche Entscheidung des Nutzers nicht ausdrücken.

Diese Grenzen machen die Untersuchung von Vorfällen deutlich weniger spekulativ. Ein Prüfer kann feststellen, dass ein bestimmtes signiertes Programm lief, dass eine Person diesen Lauf freigegeben hat und dass der Lauf Berechtigung für eine definierte Aktion erhielt. Ohne alle drei Datensätze lässt selbst eine perfekte DR die wichtigste Frage offen: Was durfte der wiedererkannte Prozess tun?

Freigabebildschirme sollten sagen, was bewiesen wurde

Ein Mensch kann bei einer unterbrechenden Freigabe kein rohes Requirement-Blob prüfen. Zeigen Sie eine kompakte Aussage aus validierten Daten: Signierer oder Team, Signing Identifier, Signaturkategorie, Pfad zur ausführbaren Datei und ob die Freigabe für den Prozess oder einen einzelnen Aufruf gilt. Stellen Sie die umfassendste Information nur dann zuerst dar, wenn das Design bewusst umfassende Berechtigung vergibt.

Vermeiden Sie freundliche App-Namen als primäre Identität. Anzeigenamen stammen aus veränderbaren Metadaten und sind oft nicht eindeutig. Nach den validierten Signaturdaten sind sie nützliche Beschriftungen, ähnlich wie der Pfad. Eine Freigabe mit dem Text Example Agent wants access verschleiert, ob der Anfragende die veröffentlichte App, ein Hilfsprogramm, ein lokaler Neubau oder eine unsignierte Kopie ist.

Sallyport zeigt beim ersten Aufruf eines neuen Agentenprozesses eine Freigabekarte, die von der Code-Signing-Autorität des Prozesses angeführt wird, und bindet die Freigabe dann an diesen Lauf, bis er endet. Seine Tresorsperre und das Flag für Freigabe bei jedem Aufruf bleiben getrennte Kontrollen. Das Wiedererkennen eines Prozesses wird daher nie zu unbegrenztem Zugriff auf Geheimnisse.

Das Auditereignis sollte festhalten, was der Prüfer beobachtet und welche Regel er angewandt hat. Speichern Sie die validierte Kategorie, Team ID, Signing Identifier, Requirement-Referenz, Pfad, Prozess- und Sitzungskennungen, Entscheidung, Ablehnungsgrund und Freigabeumfang. Ein späterer Prüfer sollte die aktuelle Datei am alten Pfad nicht brauchen, um den Aufruf zu verstehen.

Nennen Sie das Ergebnis nicht trusted process. Der Prüfer hat etwas Engeres bewiesen: Dieser Live-Prozess erfüllte eine bestimmte Code-Requirement, und ein Nutzer oder eine Richtlinie gab ihm eine definierte Aktion frei. Diese Formulierung schützt vor schleichender Ausweitung von Berechtigungen, wenn neue Geheimnistypen und Agentenwerkzeuge hinzukommen.

Eine Team ID gehört in diese Aussage, kann sie aber nicht allein tragen. Verwenden Sie die Team ID, um den Signierer zu benennen, den Signing Identifier, um das Programm innerhalb dieses Signierers zu benennen, die Designated Requirement, um die Identität über legitime Releases hinweg zu erhalten, und das Live-Prozesshandle, um den Nachweis an den Anfragenden zu binden. Fehlt eines dieser Elemente, grenzen Sie die Freigabe ein oder fragen Sie erneut.

FAQ

Können zwei verschiedene macOS-Apps dieselbe Team ID haben?

Ja. Jede App und jedes Hilfsprogramm, die vom selben Apple-Entwicklerteam signiert wurden, können dieselbe Team ID haben. Verwenden Sie die Signing Identifier oder eine Designated Requirement, um Programme innerhalb des Teams zu unterscheiden.

Ist eine Bundle-ID dasselbe wie ein Signing Identifier?

Oft, aber macOS verlangt das nicht. Der Signierer wählt den Signing Identifier, und Kommandozeilentools können einen haben, ohne zu einem App-Bundle zu gehören. Lesen Sie ihn daher aus der validierten Code-Signatur aus.

Sollte ich eine Designated Requirement oder Felder für Team ID und Identifier speichern?

Speichern Sie die maschinell auswertbare Designated Requirement und behalten Sie Team ID sowie Signing Identifier als lesbare Auditdaten. Werten Sie die Requirement mit Code Signing Services aus, statt ihren ausgegebenen Text zu analysieren und zu vergleichen.

Beweist eine Designated Requirement, dass ein Prozess sicher ist?

Nein. Sie belegt, dass Code einen Identitätsausdruck erfüllt. Sie brauchen weiterhin eine separate Entscheidung darüber, welche Geheimnisse und Aktionen diese Identität wie lange und mit welcher menschlichen Freigabe nutzen darf.

Kann ein ausführbarer Pfad Teil der Prozessautorisierung sein?

Sie kann nach erfolgreicher Signaturprüfung als zusätzliche Standortbeschränkung dienen. Ein Pfad allein ist unsicher, weil Dateien verschoben werden können und Angreifer eine Datei an einem freigegebenen, beschreibbaren Ort ersetzen könnten.

Wie sollte ein Dienst den Prozess einer IPC-Verbindung identifizieren?

Leiten Sie den Kommunikationspartner aus vom Kernel bereitgestellten Verbindungsdaten wie einem Audit-Token ab und validieren Sie dann das zugehörige Live-Codeobjekt. Vertrauen Sie niemals einer PID, einem Pfad oder einem Identifier aus der Anfrage des Clients.

Was passiert mit der Berechtigung, wenn sich eine signierte App aktualisiert?

Eine richtig gewählte Designated Requirement sollte legitime Updates weiterhin als dieselbe Identität akzeptieren. Ändern sich Signierer, Identifier oder Distributionsweg außerhalb dieser Requirement, verlangen Sie eine ausdrückliche Identitätsmigration oder eine neue Freigabe.

Kann ich einen unsignierten Entwicklungs-Build dauerhaft autorisieren?

Sie können das tun, doch eine dauerhafte pfadbasierte Freigabe bietet keine verlässliche Codekontinuität. Besser ist eine entwicklungsbezogene Freigabe für die Prozesslaufzeit, die an genau diesen Build gebunden, auf Nicht-Produktionsgeheimnisse beschränkt ist und nach jedem Neubau erneut abgefragt wird.

Sollte ein Kindprozess die Identität seines signierten Elternprozesses erben?

Nicht automatisch. Wenn das Kind eine Verbindung aufbaut, ist es der direkte Kommunikationspartner. Das Hochlaufen im Prozessbaum kann ersetzten Nachkommen Berechtigungen verleihen. Reichen Sie eine begrenzte Capability über einen kontrollierten Kanal weiter, wenn Vererbung Teil des Designs ist.

Ist ein Code-Hash eine bessere Identität als eine Team ID?

Ein Hash identifiziert exakte Codebytes und eignet sich daher gut für eine zeitlich begrenzte Ausnahme für unsignierte Builds. Er überlebt keine legitimen Updates, während Team ID plus Signing Identifier oder eine Designated Requirement Kontinuität über Releases hinweg ausdrücken können.

Sallyport

Sallyport führt API-Aufrufe und SSH-Befehle für Ihren KI-Agenten aus. Die Schlüssel bleiben in einem lokalen Tresor auf Ihrem Mac; Sie geben jeden Lauf frei, und jede Aktion landet in einem versiegelten Journal.

© 2026 Sallyport · Open Source unter Apache-2.0 · Oleg Sotnikov