Nach dem Fehlschlagen einer Pipeline lädt ein Team üblicherweise das vollständige Protokoll, Testanhänge und Ergebnispakete in einen gemeinsam genutzten Speicher hoch. Anschließend übernimmt ein anderer Entwickler die Fehleranalyse. Die eigentliche Gefahr ist dabei nicht die auffällige Zeile TOKEN=, sondern sie liegt in Befehlsargumenten, die im Debugmodus ausgegeben werden, in Anfrage-Headern, temporären Signierungspfaden und den von Testcode erfassten Umgebungsdaten. Wenn ein Cloud-Mac über längere Zeit mehrere Aufträge verarbeitet, können solche Informationen außerdem in Caches und Archive gelangen. Deshalb müssen sensible Daten an drei Stellen entfernt werden: direkt an der Ausgabequelle, innerhalb der Pipeline und am Freigabe-Gate vor dem Upload.
Zuerst den Datenfluss der Protokolle erfassen
Beginnen Sie nicht mit einem einzigen regulären Ausdruck, der sämtliche Texte abdecken soll. Erfassen Sie zunächst, wo Informationen eingehen, welche Prozesse sie durchlaufen und wo sie letztlich gespeichert werden.
| Eingang | Typischer Leckpfad | Vorrangige Maßnahme |
|---|---|---|
| Shell | set -x gibt expandierte Variablen aus |
Tracing vor sensiblen Schritten deaktivieren |
| Befehlsargumente | Schlüssel und Tokens erscheinen direkt in den Prozessargumenten | Geschützte temporäre Datei oder Standardeingabe verwenden |
| Umgebungsvariablen | Diagnoseskripte geben die vollständige Umgebung aus | Nur Einträge aus einer Positivliste ausgeben |
| Tests | Anfrage-Header und Kontodaten werden in Anhänge geschrieben | Daten zentral in der Test-Hilfsschicht bereinigen |
| Ergebnispaket | Screenshots, Aktivitätsprotokolle und Diagnosedateien werden vollständig hochgeladen | Nach dem Export scannen und erst danach freigeben |
Durch eine nachträgliche Bereinigung wird ein bereits offengelegter Schlüssel nicht wieder sicher. Sobald feststeht, dass ein echter Wert in ein teilbares Protokoll gelangt ist, darf das betreffende Artefakt nicht veröffentlicht werden. Der Schlüssel muss entsprechend seinem Typ ausgetauscht werden.
Legen Sie auf dem OakVM-Knoten zunächst für jeden Auftrag ein eigenes Verzeichnis an und beschränken Sie die Lese- und Schreibrechte auf den aktuellen Benutzer. Speichern Sie Protokolle, Ergebnispakete und zum Upload vorgesehene Dateien getrennt, damit geprüfte Dateien nicht mit den Originaldateien vermischt werden.
umask 077
run_id="$(date -u +%Y%m%dT%H%M%SZ)-$$"
root="$HOME/ci-runs/$run_id"
mkdir -p "$root/raw" "$root/safe" "$root/results"
Leckpfade direkt an der Ausgabequelle schließen
Keine Geheimnisse in Befehlsargumenten übergeben
Prozessargumente können von Diagnosewerkzeugen, Absturzprotokollen oder Skripten ausgelesen werden, die unter demselben Benutzerkonto laufen. Rufen Sie ein internes Uploadskript daher nicht mit --token "$TOKEN" auf. Sicherer ist es, wenn das Skript den Wert aus einer temporären Datei mit den Rechten 600 liest und diese unmittelbar nach der Verwendung löscht. Unterstützt das Werkzeug die Standardeingabe, kann der Wert auch darüber übergeben werden.
Shell-Tracing sollte standardmäßig deaktiviert sein. Wenn gewöhnliche Befehle beobachtet werden müssen, aktivieren Sie es nur für einen kurzen Abschnitt, in dem keine sensiblen Variablen verwendet werden. Führen Sie set +x aus, bevor Anmeldedaten geladen werden. Auch die vollständige Ausgabe der Umgebung muss unterbleiben. Beschränken Sie Diagnoseinformationen stattdessen auf eine Positivliste:
printf 'PATH=%s
' "$PATH"
printf 'DEVELOPER_DIR=%s
' "$DEVELOPER_DIR"
xcodebuild -version
sw_vers
Auch Pfade sind als sensible Informationen zu behandeln. Benutzernamen, interne Projektbezeichnungen und temporäre Signierungsverzeichnisse können Rückschlüsse auf die Teamstruktur zulassen. Vor der Veröffentlichung eines Protokolls lässt sich das Stammverzeichnis des Arbeitsbereichs durch $WORKSPACE ersetzen. Dateinamen und Zeilennummern sollten jedoch erhalten bleiben, damit das Protokoll weiterhin für die Fehlersuche nutzbar ist.
Eine Bereinigungspipeline aufbauen, die Fehler nicht verschluckt
Ersetzungsregeln sollten vorrangig auf die tatsächlichen geheimen Werte reagieren und nicht lediglich nach Feldnamen wie password oder secret suchen. Solche Feldnamen führen leicht zu Fehlalarmen und erfassen zudem keine Tokens ohne Kennzeichnung. Der folgende Filter liest die zu maskierenden Werte aus einer geschützten Datei und ersetzt sie absteigend nach ihrer Länge. Dadurch kann ein kurzer Wert nicht verhindern, dass ein längerer Wert vollständig erkannt wird.
import os
import sys
from pathlib import Path
secret_file = Path(os.environ["REDACT_FILE"])
values = [
line.rstrip("
")
for line in secret_file.read_text(encoding="utf-8").splitlines()
if line.strip()
]
values.sort(key=len, reverse=True)
for line in sys.stdin:
for value in values:
line = line.replace(value, "[REDACTED]")
sys.stdout.write(line)
Beim Ausführen des Builds muss der tatsächliche Exitcode von xcodebuild erhalten bleiben. Wird nur der Status von tee am Ende der Pipeline ausgewertet, kann ein fehlgeschlagener Build fälschlich als erfolgreich gelten.
#!/bin/bash
set -o pipefail
set +x
REDACT_FILE="$root/secrets.txt" \
xcodebuild \
-workspace App.xcworkspace \
-scheme App \
-configuration Release \
-resultBundlePath "$root/results/App.xcresult" \
build 2>&1 |
python3 ci/redact.py |
tee "$root/safe/build.log"
statuses=("${PIPESTATUS[@]}")
exit "${statuses[0]}"
Für secrets.txt müssen die Rechte 600 gesetzt sein. Außerdem ist die Datei in einem Hook beim Beenden des Auftrags zu löschen. Mehrzeilige private Schlüssel eignen sich nicht für eine zeilenweise Ersetzung. Sie dürfen von vornherein nicht ausgegeben werden. In die Maskierungsdatei gehören nur stabile Identifikationswerte, die tatsächlich in Textausgaben vorkommen könnten.
Ergebnispakete und Testanhänge scannen
Ein erfolgreich geprüftes Textprotokoll bedeutet noch nicht, dass der gesamte Auftrag hochgeladen werden darf. Ergebnispakete können Test-Screenshots, Anhänge fehlgeschlagener Tests, Aktivitätsprotokolle und Diagnoseinformationen enthalten. Kopieren Sie die Daten zunächst in ein isoliertes Verzeichnis, exportieren Sie nur die Inhalte, die tatsächlich geteilt werden müssen, und scannen Sie anschließend das Exportverzeichnis. Das vollständige Ergebnispaket sollte nicht standardmäßig veröffentlicht werden.
Fehlalarme mit zwei Regelklassen reduzieren
Die erste Regelklasse gleicht die tatsächlichen Geheimnisse des aktuellen Auftrags ab. Jeder Treffer blockiert die Freigabe sofort. Die zweite Regelklasse sucht nach risikoreichen Strukturen, beispielsweise Autorisierungs-Headern, Begrenzungszeilen privater Schlüssel, URLs mit eingebetteten Anmeldedaten und verdächtig langen Tokens. Treffer aus den Strukturregeln müssen manuell geprüft werden. Nicht jedes Vorkommen von token darf automatisch als Datenleck gelten, da das Wort auch in Quelldateinamen und Testbeschreibungen enthalten sein kann.
Der Scanbericht darf nur Dateipfad, Zeilennummer und Regelnummer enthalten. Der gefundene Originaltext darf nicht erneut in den Bericht kopiert werden. Bei binären Anhängen sollte zunächst der Dateityp bestimmt werden. Dateien, die sich nicht sicher analysieren lassen, gehören standardmäßig nicht in freigegebene Artefakte. Ihr Inhalt darf nicht einfach mit strings extrahiert und anschließend veröffentlicht werden.
Die Bereinigung zum Freigabe-Gate machen
Ein wartbares Freigabe-Gate muss mindestens vier Zustände berücksichtigen: den Exitcode des Builds, den Scan auf exakte Werte, die Prüfung der Strukturregeln und die Positivliste der Artefakte. Solange auch nur einer dieser Punkte nicht abgeschlossen ist, darf der Upload nicht beginnen.
Am Ende jedes Auftrags sollten folgende Punkte geprüft werden:
- Ist das Originalverzeichnis weiterhin ausschließlich für den aktuellen Benutzer zugänglich?
- Enthalten die Protokolle noch das Stammverzeichnis des Arbeitsbereichs, Autorisierungs-Header oder tatsächliche Geheimnisse?
- Enthält das Ergebnispaket unnötige Screenshots, Netzwerkantworten oder Umgebungsdaten?
- Umfasst die Uploadliste ausschließlich bereinigte Protokolle, erforderliche Berichte und ausdrücklich ausgewählte Anhänge?
- Löscht das Bereinigungsskript die geheimen Dateien, ohne sichere Kopien zu entfernen, die noch für die Fehleranalyse benötigt werden?
Führen Sie abschließend einen negativen Funktionstest durch: Speisen Sie ein eigens dafür vorgesehenes, unechtes Token in einen temporären Auftrag ein und lassen Sie es nacheinander über die Standardausgabe, die Fehlerausgabe und einen Testanhang laufen. Prüfen Sie, ob das Freigabe-Gate den Upload jeweils blockiert. Lassen Sie den Build danach absichtlich mit einem von null verschiedenen Status enden und vergewissern Sie sich, dass die Bereinigungspipeline den fehlgeschlagenen Build nicht als erfolgreich meldet. Erst wenn beide Testarten bestanden sind, ist die Protokollsicherheit tatsächlich in den Entwicklungsprozess integriert.
Häufig gestellte Fragen
Reicht eine Ersetzung sensibler Wörter unmittelbar vor dem Upload?
Nein. Werte können bereits in Terminalausgaben, temporären Dateien oder Ergebnis-Bundles stehen. Debug-Ausgaben und unsichere Befehlsargumente müssen zuerst vermieden werden.
Wie bleibt der echte Exitcode von xcodebuild in einer Filter-Pipeline erhalten?
Aktivieren Sie pipefail in Bash und speichern Sie direkt nach der Pipeline PIPESTATUS[0]. Der Exitcode von tee oder vom Filter darf das Buildergebnis nicht ersetzen.
Welche Dateien sollten zusätzlich zum Textprotokoll geprüft werden?
Prüfen Sie Ergebnis-Bundles, Testanhänge, Diagnosearchive, exportierte Konfigurationen und Berichte eigener Skripte.
Den nächsten Build auf einem dedizierten physischen Knoten ausführen
Wählen Sie OakVM M4 oder OakVM M4 Pro und mieten Sie einen Cloud-Mac ohne Virtualisierung – tage-, wochen-, monats- oder quartalsweise. Der aktuelle Verfügbarkeitsstatus des Knotens wird in Echtzeit von der Konsole angezeigt.