# Sensible Daten in Absturzberichten: Leaks aus dem Agent-Kontext verhindern

Die Absturzberichterstattung kann sich unbemerkt zum breitesten Datenexportpfad einer Anwendung mit Agenten entwickeln. Teams sichern Produktionszugänge ab und lassen dann ein Exception-SDK Breadcrumbs, HTTP-Kontext, Prozessdetails und kopierte Tool-Eingaben erfassen, bevor es das Paket an ein Anbieter-Konto sendet. Der Absturz war lokal. Die Belege blieben es nicht.

Die Lösung besteht nicht darin, Absturzberichte aufzugeben. Du brauchst sie, wenn eine Agent-Integration auf eine Weise fehlschlägt, die sich mit gewöhnlichen Logs nicht erklären lässt. Entscheidend ist, festzulegen, welche Debugging-Informationen den Rechner verlassen, standardmäßig keine rohen Request-Daten zu erfassen und nachzuweisen, dass der Collector diese Grenzen einhält. Ich habe erlebt, wie Untersuchungen zu Sicherheitsvorfällen ins Stocken gerieten, weil der Stack-Trace harmlos war, ein «nützliches» Kontextfeld aber den gesamten fehlerhaften Request enthielt.

## Absturzberichte sind Beweispakete, nicht nur Stack-Traces

Ein Absturzbericht ist oft ein Paket, das über mehrere Ebenen hinweg zusammengestellt wird. Das Betriebssystem kann einen nativen Diagnosebericht erstellen. Deine Anwendung kann Metadaten zur Ausnahme anhängen. Ein Crash-SDK kann Gerätedaten, Breadcrumbs, Sitzungsverlauf, Logs, Tracing-Felder und benutzerdefinierte Tags ergänzen. Ein Agent-Framework kann seinen Prompt, seine Tool-Eingabe, seine Antwort oder seinen Wiederholungsstatus bereits in eines dieser Felder serialisiert haben.

Diese Unterscheidung ist wichtig, weil Entwickler meist den sichtbaren Stack-Trace prüfen und das Ergebnis als sauber betrachten. Die sensiblen Daten liegen normalerweise daneben.

Ein Bericht kann Daten über Folgendes preisgeben:

- Ausnahmemeldungen, in die eine URL, ein Befehl oder ein Antworttext eingefügt wurde
- Breadcrumbs aus Request-Logs oder Tool-Aufruf-Ereignissen
- benutzerdefinierte Felder, die ein vollständiges Request-Objekt aufnehmen
- Kommandozeilenargumente, Pfade zu temporären Dateien und aus der Umgebung abgeleitete Werte
- angehängte Dateien, Screenshots, Session Replay oder Support-Feedback

Eine Speicheradresse in einem nativen Bericht verrät normalerweise allein keinen API-Schlüssel. Eine Zeichenfolge, die in eine Panic-Meldung kopiert wurde, kann das sehr wohl. Vermische diese beiden Fälle nicht. Native Diagnosedaten brauchen Zugriffskontrollen; bei Anwendungstelemetrie ist eine gezielte Datenminimierung nötig.

Apples Dokumentation zu Diagnoseberichten beschreibt sie als Aufzeichnungen zur Untersuchung von Anwendungsproblemen mit Informationen zu Prozessen und Threads. Das ist nützlich und meist deutlich weniger umfangreich als ein Application-Monitoring-Ereignis. Sobald ein SDK diesen Bericht jedoch mit deinem eigenen Laufzeitkontext anreichert, ändert sich die Datengrenze. Behandle das angereicherte Ereignis als Anwendungsdaten, die an ein anderes System geschickt werden.

## Agent-Fehler erzeugen besonders umfangreichen Diagnosekontext

Ein gewöhnlicher Request-Handler kann mit einer Route und einem Statuscode fehlschlagen. Eine Agent-Aktion kann eine Benutzeranweisung, Repository-Pfade, Kommandoausgaben, Argumente für eine entfernte API, ein SSH-Ziel und frühere Tool-Ergebnisse enthalten, die zum Fehler geführt haben. Dieser Kontext hilft bei der Reproduktion des Fehlers. Unachtsame Erfassung macht ihn aber auch kostspielig.

Der riskante Ablauf ist vorhersehbar. Ein Entwickler versieht jeden Tool-Aufruf mit einem komfortablen Logger. Der Logger gibt das vollständige Argumentobjekt aus. Das Observability-SDK wandelt Log-Einträge in Breadcrumbs um. Ein Netzwerk-Timeout löst eine Ausnahme aus. Der Bericht enthält nun die Tool-Eingabe, einschließlich Headern oder eines eingefügten Tokens, und der Anbieter erhält sie.

Dasselbe passiert bei folgendem Code:

```js
try {
  await runTool(toolName, input);
} catch (error) {
  throw new Error(`Tool failed: ${toolName} input=${JSON.stringify(input)} error=${error.message}`);
}
```

Die Meldung wirkt bei einem lokalen Test hilfreich. In der Produktion erzeugt sie ein unbeschränktes Datenfeld, das jeder Fehler-Collector, jedes Log-Ziel und jede Alert-Integration kopieren kann. Ersetze sie durch stabile Kennungen und eine Zusammenfassung aus erlaubten Feldern:

```js
try {
  await runTool(toolName, input);
} catch (error) {
  throw new Error(`Tool failed: name=${toolName} request_id=${requestId} input_shape=${inputShape}`);
}
```

`inputShape` kann eine Liste genehmigter Feldnamen und Größen enthalten, aber niemals Feldwerte. Wenn du nicht erklären kannst, warum ein Feld in ein Fehlerereignis gehört, lass es weg. Die Reproduktion sollte mit einer Korrelations-ID beginnen, die auf einen geschützten lokalen Datensatz verweist, nicht mit einem vollständigen Request in einem gehosteten Dashboard.

## Die Erfassung roher Requests ist ein schlechter Standard

Die Erfassung roher Requests bleibt beliebt, weil sie die erste Fehlersuche beschleunigt. Für Dienste, die Agent-Aktionen verarbeiten, ist sie als Standard falsch. Autorisierungs-Header, Cookies, signierte URLs, Query-Parameter, Request-Bodies und benutzerdefinierte Header enthalten regelmäßig Daten, die in einem Absturzsystem nichts zu suchen haben.

Ein sicheres Ereignis enthält genug Informationen, um den Vorfall zu gruppieren, zu priorisieren und weiterzuleiten:

```json
{
  "request_id": "rq_8c2f1a",
  "channel": "http",
  "method": "POST",
  "route": "/v1/issues/{issue_id}/comments",
  "status_class": "5xx",
  "duration_ms": 8120,
  "attempt": 2,
  "error_kind": "upstream_timeout"
}
```

Die Route verwendet ein Template, nicht den tatsächlichen Pfad. Das Ereignis sagt, dass der Request wiederholt wurde, aber nicht, was er gesendet hat. Die undurchsichtige ID ermöglicht es einem autorisierten Bearbeiter, bei Bedarf den lokalen Quelldatensatz einzusehen.

Hashe keine Geheimnisse und nenne sie dann redigiert. Ein deterministischer Hash kann ein wiederholt verwendetes Bearer-Token weiterhin identifizieren und ist angreifbar, wenn der ursprüngliche Wert aus einem kleinen Suchraum stammt. Ersetze sensible Werte durch eine konstante Markierung oder lass sie weg. Wenn du nur wissen musst, ob ein Zugang vorhanden war, erfasse `auth_present: true`, nicht Typ, Länge, Präfix oder Fingerabdruck.

Prüfe auch den Umgang mit URLs. Viele Bibliotheken zeichnen vollständige URLs automatisch auf. Eine Route wie `/callback?code=...` oder eine signierte Download-URL kann durch ein Feld nach außen gelangen, das der Entwickler nie manuell hinzugefügt hat. Entferne Query-Strings, bevor das Ereignis das SDK erreicht, statt darauf zu hoffen, dass ein späterer Prozessor jede Variante erkennt.

## Redaction muss vor Speicherung und Export erfolgen

Ein Scrubber ist eine Rückfallebene, aber keine Erlaubnis, alles zu erfassen. SDK-Hooks funktionieren unterschiedlich: Manche verarbeiten das fertige Ereignis, manche nur ausgewählte Felder, und manche decken native Absturzanhänge oder Breadcrumbs aus einer separaten Integration nicht ab. Eine Regel, die `Authorization` redigiert, kann `authorization`, `x-api-token`, einen URL-Parameter oder einen in einer Ausnahme eingebetteten JSON-String übersehen.

Baue die Grenze in mehreren Schichten auf. Deaktiviere zuerst die automatische Erfassung, die du nicht brauchst. Erstelle dann Ereignisse aus erlaubten Feldern. Führe anschließend einen defensiven Scrubber über alle verbleibenden Zeichenfolgen aus. Teste zum Schluss die serialisierten Daten, die der Collector empfängt.

Dieses Pseudocode-Beispiel zeigt die Reihenfolge, die die meisten Probleme verhindert:

```text
request arrives
  -\u003e derive route template and request ID
  -\u003e retain protected local diagnostic record if policy permits
  -\u003e create minimal crash context from allowlisted fields
  -\u003e scrub all residual strings
  -\u003e send minimized event
```

Übergib dem «before send»-Callback nicht das ursprüngliche Request-Objekt. Sobald eine Bibliothek dieses Objekt geprüft hat, können Plugins daraus bereits Breadcrumbs oder Spans erstellt haben. Gib dem Telemetriecode ein kleines Objekt, das von vornherein keine sensiblen Felder enthalten kann.

Sentry dokumentiert Datenbereinigung und Event-Prozessoren, Firebase Crashlytics dokumentiert benutzerdefinierte Schlüssel und die Erfassung von Logs. Lies diese Einstellungen als Steuerung der Datenerfassung, nicht als allgemeine Datenschutzgarantie. In beiden Fällen sind benutzerdefinierter Kontext und Logs die Stellen, an denen Anwendungsteams ihre eigenen Standardschutzmaßnahmen am häufigsten aushebeln.

## SDK-Standards ändern sich mit neuen Integrationen

Ein Upgrade des Crash-SDKs kann Tracing, Konsolenerfassung, Breadcrumbs, Session Replay, Performance-Instrumentierung oder eine Framework-Integration hinzufügen, die mehr Request-Zustand sieht. Eine Sicherheitsprüfung aus der Zeit, als die App nur Stack-Traces erfasste, deckt den neuen Datenpfad nicht ab.

Führe für jede Laufzeit ein kleines Verzeichnis der Datenerfassung. Halte den nativen Crash-Collector, das Exception-SDK, die Logging-Brücke, das Tracing-Paket, das Feedback-Widget und den Mechanismus für Support-Pakete fest. Beantworte für jedes davon vier alltägliche Fragen: Was löst die Erfassung aus? Welche Felder werden automatisch erfasst? Wo werden die Daten vor dem Upload gespeichert? Wer kann sie nach dem Upload lesen?

Vergiss Seitenkanäle nicht. Entwickler deaktivieren im Crash-Produkt oft Request-Bodies, leiten dieselbe Ausnahme aber an einen Log-Aggregator weiter. Alert-Regeln können den Ausnahme-Text in Chat-Benachrichtigungen kopieren. Eine Support-Schaltfläche kann ein lokales Log-Archiv anhängen. Du brauchst eine Datenkarte für den gesamten Vorfallspfad, nicht für jeden Anbieter eine eigene, optimistische Darstellung.

Prüfe unter macOS sowohl die Berichterstattung der App als auch die Diagnosedaten des Betriebssystems. Apple-Absturzberichte können lokal bleiben oder über die Einstellungen zur Systemberichterstattung geteilt werden, während Drittanbieter-SDKs ihrer eigenen Konfiguration und ihrem eigenen Netzwerkpfad folgen. Eine Desktop-App sollte diesen Unterschied für die zuständigen Personen klar machen. «Absturzberichte sind deaktiviert» bedeutet nichts, wenn ein separates Fehlerüberwachungs-Client weiterhin angereicherte Ereignisse hochlädt.

## Halte Zugangsdaten außerhalb des Agent-Prozesses

Redaction verringert die Offenlegung, nachdem der Code ein Geheimnis bereits verarbeitet hat. Besser ist es, zu verhindern, dass der Agent-Prozess das Geheimnis überhaupt erhält. Dann stehen bei einem Agent-Absturz, einer kopierten Umgebung und einem versehentlichen Debug-Dump weniger sensible Daten zur Erfassung bereit.

Das macht einen Absturzbericht nicht automatisch harmlos. Der Agent kann weiterhin privaten Quellcode, Prompts oder Tool-Argumente im Speicher halten. Ein Bearer-Token kann jedoch nicht aus einem Prozess entweichen, der es nie erhalten hat.

Sallyport folgt dieser Grenze bei HTTP-APIs und SSH-Aktionen: Die App bewahrt Zugangsdaten in ihrem verschlüsselten Tresor auf, führt die Aktion aus und gibt das Ergebnis an den Agenten zurück, statt ihm Zugangsdaten zu überlassen. Dadurch entfällt ein wiederkehrender Fehlerweg bei der Absturztelemetrie. Trotzdem musst du die Request-Daten und Ergebnistexte minimieren, die dein Agent verarbeitet.

Vermeide Geheimnisse auch in Kommandoargumenten. Prozessargumente tauchen in Diagnosetools häufiger auf, als Entwickler erwarten, und Shell-Verlauf oder Prozessinspektion können sie unabhängig von der Absturzberichterstattung offenlegen. Übergib geheime Daten über einen geschützten Broker oder einen sorgfältig verwalteten lokalen Mechanismus, nicht über ein sichtbares Argument wie `--token=...`.

## Auch die lokale Aufbewahrung braucht eine Regel

Vollständige Berichte auf dem Rechner aufzubewahren kann bei schwierigen Fehlern sinnvoll sein, besonders während einer kontrollierten Entwicklung. Sicher ist das nicht automatisch. Ein lokaler Spool kann den Vorfall überdauern, in ein Support-Archiv kopiert werden oder in einem gemeinsam genutzten Benutzerprofil liegen, auf das ein anderer Prozess zugreifen kann.

Trenne zwei Datensätze. Sende ein minimiertes Remote-Ereignis zum Gruppieren und Alarmieren. Bewahre einen ausführlicheren Reproduktionsdatensatz bei Bedarf lokal an einem geschützten Ort mit kurzer Aufbewahrungsfrist und einem klaren Löschweg auf. Das Remote-Ereignis braucht die undurchsichtige ID des lokalen Datensatzes, nicht dessen Inhalt.

Ein nützlicher lokaler Datensatz enthält die genaue Build-Kennung, einen bereinigten Konfigurationsfingerabdruck, Zeitangaben und einen Verweis auf den Aktionsversuch. Er sollte keine lose Textdatei sein, die Umgebungsvariablen, Request-Bodies und Terminalausgaben aneinanderhängt. Strukturierter lokaler Speicher ermöglicht dieselben Regeln für erlaubte Felder und Löschung, die du auch für Exporte verwendest.

Bei Gateways für Agent-Aktionen verdienen Audit-Datensätze besondere Aufmerksamkeit. Sie helfen nachzuvollziehen, was der Agent versucht hat, sind aber keine Erlaubnis, rohe Zugangsdaten oder vollständige Prompts in jedes Diagnosesystem zu spiegeln. Sallyports Audit-Spur trennt Aktionsdatensätze vom Agenten selbst. Der Befehl `sp audit verify` prüft die verschlüsselte Hash-Kette offline ohne Tresorschlüssel. Die Prüfung zeigt, ob die Spur verändert wurde. Welche Diagnoseinformationen an anderer Stelle hingehören, entscheidet weiterhin die Datenminimierung.

## Weise Geheimnisse nach, um den Collector zu prüfen

Eine Konfigurationsprüfung findet offensichtliche Fehler. Ein Test mit absichtlich platzierten Daten findet die Fehler, die wirklich zählen. Führe ihn vor dem Start, nach Upgrades des Telemetrie-SDKs und immer dann aus, wenn ein Agent-Framework ein neues Tool oder eine neue Logging-Integration erhält.

Verwende eindeutige Markierungszeichenfolgen, die nicht mit echten Zugangsdaten verwechselt werden können. Platziere verschiedene Markierungen an den Stellen, die Teams regelmäßig vergessen: in einem Autorisierungs-Header, einem Query-Parameter, einem JSON-Body-Feld, einer Agent-Anweisung, einer Umgebungsvariablen, einem Kommandoargument und einem Tool-Ergebnis. Löse eine kontrollierte Ausnahme aus und durchsuche anschließend jedes Ziel.

Prüfe die Ereignisansicht des Anbieters, den Rohdatenexport, sofern verfügbar, den lokalen Crash-Spool, Anwendungslogs, Tracing-Ereignisse, Alert-Payloads, Support-Anhänge und jede Warteschlange zwischen App und Collector. Suche nach den exakten Markierungen und nach häufigen Umwandlungen wie URL-Encoding oder maskiertem JSON. Nur das Web-Dashboard zu prüfen führt dazu, dass ein Leak in einem Breadcrumb oder angehängten Log unentdeckt bleibt.

Schreibe das erwartete Ergebnis auf. Ein Bericht darf zum Beispiel `route=/v1/files/{file_id}` und `request_id=rq_test_01` enthalten, aber nicht `MARKER_HEADER_7`, `MARKER_PROMPT_7` oder den wörtlichen Query-String. Behandle einen fehlgeschlagenen Test wie einen Sicherheitsmangel: Deaktiviere den problematischen Erfassungspfad, füge einen Regressionstest hinzu und teste das serialisierte Ereignis erneut.

## Eine kurze Prüfung findet die meisten versehentlichen Exporte

Prüfe die Absturztelemetrie immer dann, wenn jemand die Fehlerbehandlung, Observability, ein Agent-Tool oder die Supportdiagnose ändert. Der Prüfer sollte fragen, ob der neue Code ein Objekt in Form eines Requests serialisieren kann, nicht nur, ob ein neues Geheimnisfeld hinzugekommen ist.

Verwende bei der Prüfung diese kurze Checkliste:

- Fehlermeldungen enthalten Kennungen und Kategorien, keine serialisierten Ein- oder Ausgaben.
- Die Telemetrie erhält erlaubten Kontext, niemals einen rohen Request oder ein Agent-Statusobjekt.
- URLs verlieren Query-Strings, und Header gelangen nie in Breadcrumbs oder benutzerdefinierte Felder.
- Vollständige lokale Diagnosedaten liegen geschützt, haben Löschregeln und einen ausdrücklich benannten Zweck.
- Ein Test mit gesetzten Markierungen deckt jedes konfigurierte Exportziel ab.

Der unangenehme Teil ist, dass gute Debugging-Gewohnheiten oft den Leak verursachen. Entwickler ergänzen Kontext, weil beim letzten Vorfall wichtige Informationen fehlten. Behalte den Kontext, der den Fehler klassifiziert, bewahre ausführlichere Belege bei berechtigtem Bedarf unter lokaler Kontrolle auf und exportiere keine rohen Daten, nur weil ein Crash-SDK dafür ein Feld anbietet.
