Zum Hauptinhalt springen

Trust und Sicherheit

compile und tests führen Code aus deinem Projekt aus: das Paketmanifest, Build-Tool-Plugins, Build-Einstellungen und die Tests selbst. Deshalb startet CodeGuard sie nur mit einer ausdrücklichen Freigabe. Diese Seite erklärt, wie diese Freigabe funktioniert.

Zwei Wege zur Freigabe​

ProfilFreigabeIm Bericht
lokal (ohne --ci)Trust-Ticket aus codeguard trust grantrun.build_authorization: "local_trust"
CI (--ci)Attestierung einer ephemeren, isolierten Umgebung durch die Organisationrun.build_authorization: "operator_attested"

Die beiden Wege schließen sich aus. Unter --ci gilt ein lokales Ticket nie, und eine Attestierung gilt nie lokal. Keine Umgebungsvariable gewährt oder entzieht eine Freigabe.

Ohne Freigabe laufen alle statischen Prüfungen, compile und tests landen unter Skipped, und der Bericht enthält:

1. ERROR
Rule: codeguard-build-execution-denied
Build and test execution was not authorized: project trust is not-trusted; grant trust before running builds or tests.
Grant project trust, or run inside an attested isolated environment.

Ohne andere Fehler endet der Lauf mit Exit 6. Gibt es zusätzlich blockierende Funde aus den statischen Prüfungen, ist der Exit-Code 1 und policy_blocked steht unter secondary_failures.

check-file braucht nie eine Freigabe, weil es nie baut oder testet.

Trust-Ticket erteilen​

codeguard trust grant --duration 8h
  1. CodeGuard zeigt die Ausführungsoberflächen (siehe unten) auf stderr.
  2. Es fragt Grant trust for 8h? Type 'yes' to continue:.
  3. Nur yes erteilt das Ticket. Alles andere endet mit Exit 6 (project trust was not granted).

Das Ticket gilt höchstens 24 Stunden. trust grant verlangt ein interaktives Terminal und ist unter --ci verboten (jeweils Exit 6). Es bindet automatisch die .codeguard.yml im Projektwurzelverzeichnis, wie sie auch ein check-*-Lauf ohne Parameter lädt.

Status anzeigen und Ticket entziehen:

codeguard trust status
codeguard trust revoke

Was ein Ticket bindet​

Ein Ticket gilt nur, solange alles hiervon unverändert ist:

  • kanonische Projektwurzel
  • aktueller Benutzer
  • configuration_hash der wirksamen Konfiguration
  • policy_hash der Organisationsrichtlinie
  • Fingerprints aller Ausführungsoberflächen im Projekt
ArtDateien (in jeder Verzeichnistiefe)
manifestPackage.swift, Package@swift-*.swift, Package.resolved
pluginPlugins/*.swift
build-script*.sh, *.command, build.swift
xcode-project*.xcodeproj/project.pbxproj, *.xcworkspace/contents.xcworkspacedata, *.xcconfig, *.xctestplan
scheme*.xcscheme

Nicht durchsucht werden .git, .build, DerivedData, xcuserdata und *.xcresult. Ein lokales swift package resolve oder ein Clean macht ein Ticket also nicht ungültig.

Ändert sich eine gebundene Angabe, meldet trust status invalid und Builds werden verweigert. Echtes Beispiel nach einem Wechsel der Konfigurationsdatei:

Build and test execution was not authorized: project trust is invalid; grant trust before running builds or tests.

Ein Ticket wird deshalb ungültig, wenn

  • du .codeguard.yml, Package.swift, das Xcode-Projekt, ein Scheme oder eine .xcconfig änderst,
  • du --config oder --no-project-config anders verwendest als beim Erteilen,
  • die Organisationsrichtlinie geändert wird,
  • CodeGuard aktualisiert wird und sich dabei Standardwerte ändern (z. B. beim Wechsel auf 0.3.4).

Dann einfach codeguard trust grant erneut ausführen.

Keychain​

Der Trust-Store ist mit einem Schlüssel aus dem Schlüsselbund geschützt (Dienst com.codeguard.control-state, Konto hmac-key-v1). version und schema brauchen ihn nicht, doctor, trust und check-* schon.

Hängender Lauf nach einem Neubau

Wurde CodeGuard neu gebaut, ist das Binary anders signiert. Passt die Zugriffsregel des vorhandenen Schlüsselbund-Eintrags nicht mehr, wartet macOS bei einem Lauf ohne grafische Sitzung (z. B. über SSH) unbegrenzt auf eine Bestätigung. Abhilfe:

  1. CodeGuard einmal in einer grafischen Sitzung starten und die Abfrage mit „Immer erlauben“ bestätigen, oder
  2. den Eintrag löschen: security delete-generic-password -s com.codeguard.control-state -a hmac-key-v1. Das macht alle lokalen Trust-Tickets ungültig.

Audit-Log​

CodeGuard schreibt sicherheitsrelevante Ereignisse in ein geräte-lokales Audit-Log. Es lässt sich nicht abschalten.

EreignisWann
trust-grantednach trust grant
trust-checkedwenn sich das Ergebnis einer Trust-Prüfung ändert (nicht bei jeder Prüfung)
security-decisionbei einem kritischen Fund, mit Regel, Datei und Fingerprint, ohne den gefundenen Wert
simulator-device-created, simulator-device-deleted, simulator-cleanup-failed, simulator-orphan-removedLebenszyklus der Wegwerf-Simulatoren

Trust-Ereignisse tragen den Modus der Projektkonfiguration (auto, explicit, disabled, none) und gegebenenfalls deren sha256, nie einen Pfad. Das Log fasst höchstens 4096 Einträge und rotiert nicht. Ein Schreibfehler ändert weder Ergebnis noch Exit-Code. Unter --ci liest trust status weder Schlüsselbund noch Trust-Store und schreibt kein Ereignis.

Was Builds auf dem Rechner berühren​

  • Xcode-Builds laufen auf einer Kopie des Projekts in einem privaten Arbeitsverzeichnis (ohne .git, .build, DerivedData, xcuserdata, *.xcresult), mit eigenem HOME und TMPDIR in diesem Verzeichnis. Die Kopie ist auf 50 000 Einträge, 2 GiB und Verzeichnistiefe 100 begrenzt. Symlinks, die aus dem Projekt herauszeigen, brechen den Lauf ab (Exit 6).
  • SwiftPM-Builds lesen das Projekt an Ort und Stelle und schreiben Build- und Cache-Verzeichnisse in das Arbeitsverzeichnis, mit leerer Umgebung.
  • SwiftPM schreibt seinen Manifest-Cache trotzdem in das echte Benutzerverzeichnis (~/Library/Caches/org.swift.swiftpm).
  • CodeGuard übergibt xcodebuild keine Signier- oder Team-Einstellungen (CODE_SIGN…, DEVELOPMENT_TEAM) und kein -allowProvisioningUpdates.
  • Das Arbeitsverzeichnis wird am Ende jedes Laufs entfernt, auch bei Fehlern und Abbruch. Bei SIGTERM oder SIGKILL bleibt es im Temp-Verzeichnis liegen (codeguard-run-<run-id>-…).

Wegwerf-Simulatoren​

Für Tests auf iOS, watchOS, tvOS und visionOS gilt:

  1. CodeGuard legt ein Gerät codeguard-<run-id>-<familie> im Standard-Device-Set des Benutzers an. Während des Laufs ist es in der Simulator-App sichtbar.
  2. Vor dem Booten schreibt es eine Lease (Besitznachweis).
  3. Nach dem Test fährt es das Gerät herunter, löscht es und entfernt die Lease, auch bei Testfehlern, Timeout und Abbruch.
  4. Höchstens ein CodeGuard-Gerät ist gleichzeitig gebootet.

Aufgeräumt wird nur, was eindeutig CodeGuard gehört: Ein Gerät ohne Lease löscht CodeGuard nie. Bleibt nach einem harten Abbruch (SIGTERM/SIGKILL) ein Gerät mit Lease zurück, räumt der nächste Lauf mit Simulator-Tests es ab. doctor zeigt solche Geräte unter Verwaiste CodeGuard-Geräte und löscht nie.

Bleibende Spuren nach dem Löschen: Logs unter ~/Library/Logs/CoreSimulator/<UDID>/, CoreSimulator.log, Nutzungsschlüssel in com.apple.CoreSimulator.plist, leere Verzeichnisse unter ~/Library/Caches/com.apple.dt.Xcode/TestReport/ und Einträge in DiagnosticReports.

Der Simulator ist keine Sandbox

Testcode läuft im Simulator mit deinen Benutzerrechten. Das Trust-Ticket bzw. die CI-Attestierung deckt das ab. Die Organisation kann Simulator-Tests mit checks.tests.simulator: false in locked_values abschalten.

Was im Bericht geschwärzt wird​

Werkzeugausgaben laufen vor dem Bericht durch eine Schwärzung. Private Pfade und erkannte Geheimnisse erscheinen als Token mit gekürztem, gerätegebundenem HMAC, zum Beispiel:

Build input file cannot be found: '<redacted:private-path:hmac-sha256:98cea2427df843611deab4a243996ee2cc23605f0f1fd88a0bd93ad6030c83f5>'.

redactions_applied: true im JSON-Bericht zeigt, dass geschwärzt wurde. Simulator-UDIDs und Pfade des Device-Sets erscheinen nie im Bericht.

Siehe auch​