8 Min. Lesezeit

Single-Process- oder daemonbasierte Sicherheitstools für Agents

Single-Process- und daemonbasierte Sicherheitstools für Agents unterscheiden sich bei lokaler Angriffsfläche, Offenlegung von Anmeldedaten, Neustartsicherheit und Betriebsaufwand.

Single-Process- oder daemonbasierte Sicherheitstools für Agents

Ein Prozessdiagramm kann ein Sicherheitsprodukt beruhigend einfach oder beeindruckend komplex wirken lassen. Keine dieser Reaktionen beantwortet die entscheidende Frage: Kann ein autonomer Coding-Agent ein Anmeldedatum missbrauchen, mit einem unbeabsichtigten lokalen Dienst sprechen oder nach einem Absturz eine Aktion ausführen, ohne dass sie protokolliert wird?

Der sinnvolle Vergleich ist konkret: Zähle die Vertrauensgrenzen, prüfe die Schnittstellen, die sie überschreiten, und verfolge ein Geheimnis vom Speicher bis zur ausgehenden Anfrage. Ein einzelner Anwendungsprozess kann lokale Komponenten reduzieren. Ein Daemon kann Berechtigungen isolieren oder einen Dienst für mehrere Clients am Leben halten. Beide Designs scheitern, wenn ihre Entwickler Prozessaufteilung mit Autorisierung verwechseln.

Die Anzahl der Prozesse definiert nicht die Sicherheitsgrenze

Bei einem Single-Process-Design liegen Benutzeroberfläche, Credential-Tresor, Freigabestatus, Anfrageprüfung, Netzwerkaktion und Protokollierung in einem Adressraum. Zwischen den eigenen Komponenten gibt es keinen lokalen Client-Socket, keine unabhängige Dienstregistrierung und kein Protokoll, mit dem ein lokaler Prozess einen anderen steuert. Das kann die Angriffsfläche spürbar verkleinern.

Gleichzeitig entsteht eine große Vertrauensdomäne. Erlangt ein Angreifer Codeausführung in diesem Prozess, kann er möglicherweise jede erreichbare Komponente nutzen. Speicherfehler, das Laden eines schädlichen Plugins, unsicheres Update-Verhalten oder eine zu großzügige Skriptschnittstelle sind besonders folgenreich, weil Tresor und Executor neben gewöhnlichem Anwendungscode liegen.

Ein daemonbasiertes Design teilt diese Aufgaben auf. Eine Desktop-Anwendung oder ein Kommandozeilen-Client sendet eine Anfrage an einen Hintergrunddienst. Der Dienst kann Geheimnisse halten und den Netzwerkaufruf ausführen, während der Client Freigaben anzeigt und Ergebnisse erhält. Das kann die Möglichkeiten eines kompromittierten Clients einschränken, aber nur dann, wenn der Daemon Anfragen ablehnt, für die der Client keine Berechtigung besitzt.

Diese Bedingung wird in Architekturgesprächen oft übersprungen. Ein Unix-Domain-Socket, der auf ein Benutzerkonto beschränkt ist, gewährt Transportzugriff. Er beweist nicht, dass der Aufrufer der vorgesehene Agent oder die freigegebene Anwendung ist. Jeder Prozess dieses Benutzers kann ihn möglicherweise öffnen. Akzeptiert der Daemon von jedem lokalen Peer eine Anfrage wie «Anmeldedaten X für URL Y verwenden», können eine schädliche Editor-Erweiterung, ein Shell-Skript oder ein kompromittierter Agent dieselbe Aktion anfordern.

Trenne diese drei Dinge:

  • Eine Prozessgrenze trennt Speicher.
  • Eine Berechtigungsgrenze begrenzt, was Code nach einer Kompromittierung tun kann.
  • Eine Autorisierungsgrenze entscheidet, welcher Aufrufer welche Aktion anfordern darf.

Teams behandeln das Erste regelmäßig als Beweis für die beiden anderen. Das ist es nicht. Zwei Prozesse, die unter demselben Benutzer mit einem nicht authentifizierten IPC-Kanal laufen, haben getrennte Heaps, können aber weiterhin zu derselben Autorisierungsdomäne gehören.

Ein einzelner Prozess vermeidet ein IPC-Autorisierungsproblem, weil seine internen Aufrufe keine lokale Dienstgrenze überschreiten. Trotzdem muss vor der Freigabe einer Aktion eine externe Agent-Sitzung identifiziert werden. Ein Daemon bringt dieses Identifikationsproblem zweimal mit sich: an seinem Client-Endpunkt und oft noch einmal an jedem administrativen Endpunkt, den er bereitstellt.

Ein lokaler Socket ist eine API, die schädlicher Code aufrufen kann

Befürworter von Daemons sagen oft zu Recht, dass der Dienst nur auf localhost oder einem Unix-Socket lauscht. Der ausgelassene Teil: Lokaler Code ist der Ort, an dem die meisten Agent-Integrationen laufen. Coding-Agent, Terminal, Editor, Build-Skripte, Paket-Hooks und Browser-Helfer teilen sich den Rechner.

Behandle einen lokalen IPC-Endpunkt wie eine kleine Netzwerk-API. Definiere Nachrichtenformate eng. Lehne unbekannte Felder ab, sofern das Protokoll dies erlaubt. Binde jede Anfrage an eine Aufruferidentität und eine kurzlebige Sitzung. Begrenze Anfragemenge, Parallelität und mögliche Ziele. Protokolliere abgelehnte ebenso wie erfolgreiche Anfragen, denn wiederholte Ablehnungen können zeigen, dass eine Integration den vorgesehenen Weg umgehen will.

Prüfe unter macOS ein Tool, bevor du seiner Aussage «nur lokal» vertraust:

ps -axo pid,ppid,user,command | grep -i '[a]gent\|[d]aemon'
lsof -nP -iTCP -sTCP:LISTEN
launchctl print gui/$(id -u) 2>/dev/null | grep -i -C 2 'agent\|vault\|security'

Der zweite Befehl gibt bei einem Prozess, der auf TCP lauscht, normalerweise Spalten in dieser Form aus:

COMMAND   PID USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
service  4128 sam     9u  IPv4 0x...            0t0  TCP 127.0.0.1:48120 (LISTEN)

Keine Ausgabe von lsof beweist nicht, dass das Tool kein IPC verwendet. Unix-Sockets erscheinen in dieser TCP-Abfrage nicht. Prüfe die Verzeichnisse für Anwendungsdaten, temporäre Verzeichnisse und die Dienstokumentation auf Socket-Pfade. Kontrolliere dann mit ls -l die Rechte und frage dich, ob ein anderer Prozess deines Kontos eine Verbindung herstellen kann.

Apples Handbuch zu launchd.plist beschreibt KeepAlive als eine Gruppe von Bedingungen, unter denen launchd einen Job neu startet. Das ist praktisch, erzeugt aber eine Sicherheitsverpflichtung. Ein neu startender Dienst muss seinen gesperrten Zustand, Sitzungsstatus und Auditstatus korrekt wiederherstellen. «Er kommt automatisch zurück» beantwortet nicht, was er in der ersten Sekunde nach dem Neustart akzeptiert.

Ein guter Daemon macht die Aufruferidentität zum Teil des Protokolls, statt sie vom Client voraussetzen zu lassen. Der genaue Mechanismus hängt vom Betriebssystem ab. Auf Plattformen, die Peer-Anmeldedaten für einen lokalen Socket bereitstellen können, solltest du diese verwenden. Wo Informationen zur Codesignatur verfügbar sind, prüfe sie vor der Freigabe einer Sitzung. Akzeptiere keinen Prozessnamen, keine im JSON mitgesendete PID und keinen vom Aufrufer angegebenen Pfad als Identität. Alle drei Werte lassen sich leicht fälschen oder sind veraltet, sobald du sie prüfst.

Das Startverhalten entscheidet, ob der Schutz im entscheidenden Moment vorhanden ist

Ein einzelner Anwendungsprozess startet normalerweise, wenn der Benutzer die App öffnet. Der Lebenszyklus der sensiblen Daten ist leicht verständlich: Die App startet, der Benutzer entsperrt sie, freigegebene Sitzungen laufen, und beim Schließen oder Absturz endet der Zugriff. Das lässt sich einfach erklären und testen.

Der Preis ist die Verfügbarkeit. Ein Kommandozeilen-Agent kann das Gateway nicht verwenden, während die App geschlossen ist, noch startet, gesperrt ist oder auf eine Systemberechtigungsabfrage wartet. Für ein von Menschen kontrolliertes Credential-Gateway kann das genau richtig sein. Es passt schlecht, wenn der vorgesehene Job nach einem Neustart unbeaufsichtigt laufen muss und das Produkt keine sichere Möglichkeit besitzt, seine Berechtigung wiederherzustellen.

Ein Daemon startet meist bei der Anmeldung, auf Anforderung oder beim Systemstart. Jede Variante verändert das Bedrohungsmodell. Ein Dienst bei der Anmeldung wartet möglicherweise auf den Schlüsselbund und die Desktop-Sitzung des Benutzers. Ein Dienst beim Systemstart kann laufen, bevor jemand etwas freigeben kann. Ein Dienst auf Anforderung verringert die Leerlauf-Exposition, aber seine erste Anfrage darf nicht mit der Initialisierung konkurrieren.

Ich habe die unschöne Variante dieses Fehlers gesehen: Die Oberfläche startet langsam, der Hintergrunddienst nimmt bereits Anfragen an und behandelt «kein Freigabestatus geladen» wie «keine Freigabe erforderlich». Entwickler bauen diesen Zweig ein, um einen Startfehler zu vermeiden. Angreifer und unzuverlässige Automatisierung interessiert der Grund nicht.

Schreibe die Zustandsmaschine auf. Sie sollte diese Fragen ohne Ausflüchte beantworten:

  1. Kann der Executor eine Anfrage annehmen, bevor der Tresor seinen gesperrten oder entsperrten Zustand meldet?
  2. Was geschieht mit einer Freigabe, die an einen Client-Prozess gebunden ist, wenn dieser Prozess endet?
  3. Was tut der Dienst nach einem Neustart, während eine Anfrage läuft?
  4. Kann eine ausstehende Benutzerabfrage einen Neustart überleben und einem anderen Aufrufer zugeordnet werden?
  5. Widerruft die Abmeldung den nutzbaren Credential-Status des Dienstes?

Bei risikoreichen Aktionen muss jeder unklare Übergang standardmäßig ablehnen. Eine Anfrage, die während der Initialisierung eintrifft, sollte eine ausdrückliche Ablehnung oder eine vorübergehende Nichtverfügbarkeit erhalten. Sie sollte keine alte Freigabe, ein entschlüsseltes Credential aus dem Cache oder eine standardmäßige Erlaubnis übernehmen.

Der Start beeinflusst auch das Verhalten der Benutzer. Wenn ein Agent-Workflow scheitert, weil jemand einen versteckten Dienst manuell wiederbeleben muss, werden Nutzer das Gate deaktivieren oder ein Token in einer Umgebungsvariable speichern. Sicherheitskontrollen, die normalen Ruhezustand, Abmeldung und Neustart nicht überstehen, bringen Nutzern bei, sie zu umgehen.

Anmeldedaten müssen den Executor erreichen, ohne durch den Agent zu laufen

Die zentrale Credential-Frage lautet nicht, ob ein Tool einen Tresor verschlüsselt. Entscheidend ist, ob der Agent das Geheimnis jemals in einer Form erhält, die er kopieren, ausgeben, in eine Datei schreiben oder an einen anderen Endpunkt senden kann.

Am sichersten bleibt das Credential in einem vom Gateway kontrollierten Tresor. Der Agent übermittelt eine Aktionsanfrage. Das Gateway prüft den Autorisierungsstatus, fügt das Credential in die ausgehende HTTP-Anfrage oder den SSH-Vorgang ein, führt die Aktion aus und gibt das Ergebnis zurück. Der Agent erhält Daten des entfernten Systems, nicht das Bearer-Token oder den privaten Schlüssel.

Dieser Unterschied ist wichtig, weil Agents mit Text arbeiten. Wenn ein Token in der Tool-Ausgabe auftaucht, kann ein Modell es in einen Shell-Befehl, eine Quelldatei, eine Problembeschreibung, ein Build-Protokoll oder einen Chatverlauf übernehmen. Ein nachträgliches Maskieren der Anzeige behebt die Offenlegung nicht. Das Geheimnis hat die Grenze bereits überschritten.

OWASPs Secrets Management Cheat Sheet rät Teams, Geheimnisse nicht fest zu codieren und sie bei vermuteter Offenlegung zu rotieren. Das ist richtig, für Agent-Workflows aber unvollständig. Ein Geheimnis kann aus der Versionsverwaltung fernbleiben und trotzdem über eine Tool-Antwort durchsickern. Das Gateway muss die Offenlegung genau in dem Moment verhindern, in dem es die Aktion ausführt.

Ein Daemon kann diese Grenze gut schützen, wenn er Entschlüsselung und ausgehende Netzwerkverbindungen besitzt. Der Client sendet eine Beschreibung der Operation, niemals eine Anfrage nach dem Klartext des Geheimnisses. Der Daemon sollte außerdem keine übermäßig ausführlichen Diagnosedaten zurückgeben. Eine fehlgeschlagene Authentifizierungsantwort darf dem Aufrufer mitteilen, dass eine Anfrage fehlgeschlagen ist. Sie muss nicht den eingesetzten Authorization-Header, eine serialisierte SSH-Konfiguration oder einen Speicherauszug des Credential-Providers enthalten.

Ein einzelner Prozess kann dieselbe Regel befolgen. Sein interner Executor liest den Tresor und führt den Aufruf aus, während der Agent über eine eingeschränkte Integrationsstelle kommuniziert. Der Vorteil: Kein zweiter Prozess braucht Zugriff auf entschlüsseltes Material. Das Risiko: Gewöhnliche Funktionen der App können im selben Speicherbereich wie das Geheimnis liegen.

Vermeide diese verlockenden Varianten:

  • API-Tokens in Umgebungsvariablen für den Agent-Prozess speichern.
  • Eine kurzlebige Credential-Datei schreiben, die ein Unterprozess liest.
  • Einen Platzhalter zurückgeben, den ein Client später gegen das echte Token eintauscht.
  • Einem lokalen Daemon aus Bequemlichkeit eine Methode «get secret» geben.
  • Private SSH-Schlüsselbytes über die Standardeingabe weitergeben.

Das Platzhaltermuster verdient besondere Skepsis. Ein Platzhalter ist nur dann sicher, wenn er außerhalb des Gateways niemals Zugriff auf ein Credential gewährt und nicht von einem anderen Prozess wiederverwendet werden kann. In der Praxis machen Teams daraus oft ein undokumentiertes Bearer-Token. Dann haben sie ein zweites Credential mit schwächeren Lebenszykluskontrollen gebaut.

Für SSH gilt dieselbe Disziplin. Ein Helfer muss möglicherweise einen Schlüssel verwenden, um eine Verbindung herzustellen. Der Agent sollte ihn aber auffordern, einen bestimmten entfernten Befehl oder eine eng begrenzte Verbindungsoperation auszuführen. Einem Agent einen privaten Schlüssel zu geben, weil er ihn «nur kurz braucht», bedeutet immer noch, ihm einen privaten Schlüssel zu geben.

Mehr Prozesse bedeuten mehr Pflege, nicht mehr Reife

Einen laufenden Agent widerrufen
Die Sitzungsfreigabe gilt nur für diesen Agent-Prozess. Das Sitzungsprotokoll ermöglicht den sofortigen Widerruf.

Ein Daemon bringt Betriebsaufwand mit sich, den eine Desktop-App mit nur einem Prozess vermeidet. Jemand muss ihn installieren, im richtigen Benutzer- oder Systemkontext starten, aktualisieren, seine Binärdatei prüfen, Abstürze behandeln, veraltete Registrierungen entfernen und nach Upgrades sicherstellen, dass Socket- und Logdateien die richtigen Eigentümer haben.

Das ist kein Argument gegen Daemons. Es ist ein Argument dagegen, so zu tun, als verschwänden diese Aufgaben im Betriebssystem. launchd kann einen Job neu starten. Es kann nicht entscheiden, ob eine neue Binärdatei weiterhin die erwarteten Aufruferprüfungen enthält, ob ein alter Socket ein Upgrade überlebt hat oder ob ein Dienst nun mit einem anderen Satz an Berechtigungen startet.

Ein Daemon erschwert außerdem die Versionskompatibilität. Ein Kommandozeilen-Wrapper kann Protokollversion A sprechen, während der installierte Dienst Version B erwartet. Behandeln die Entwickler diesen Konflikt schlecht, fällt der Client auf einen nicht authentifizierten Kompatibilitätsweg zurück oder deaktiviert Prüfungen, damit die Bedienung reibungslos bleibt. Kompatibilitätscode hat mehr Probleme verursacht, als viele Teams erwarten, weil er genau dann läuft, wenn das System am wenigsten verstanden ist.

Verwende eine ausdrückliche Ablehnung für inkompatible Versionen. Die Fehlermeldung sollte den Benutzer auffordern, eine Seite zu aktualisieren, statt stillschweigend einen schwächeren Modus auszuhandeln. Halte das Protokoll klein genug, damit du alte Clients, Dienstneustarts, fehlerhafte Nachrichten und parallele Anfragen testen kannst, ohne dafür ein eigenes Testlabor aufzubauen.

Auch Single-Process-Apps brauchen eine saubere Update-Praxis. Eine signierte Anwendung kann ihre Implementierung und ihr Tresorschema ändern. Der Unterschied ist begrenzter: Es gibt einen ausführbaren Lebenszyklus zu prüfen, und der Prozess, der die Freigabe anzeigt, ist derselbe, der die geschützte Aktion ausführt. Ein Update kann weiterhin einen Fehler einführen, aber nicht automatisch ein lokales RPC-Protokoll und einen neuen Zustand des Dienstmanagers.

Für Teams wird der Zielkonflikt deutlicher. Ein zentraler Daemon kann mehreren Tools einen stabilen lokalen Endpunkt anbieten und so doppelte Integrationen vermeiden. Er kann auch zu einem gemeinsamen Ausfallpunkt werden. Ein festgefahrener Dienst kann jeden Entwickler-Workflow auf dem Rechner blockieren. Ein Dienst mit zu weitreichenden Rechten kann jedem lokalen Client Zugriff auf jedes konfigurierte Credential geben.

Betrachte ein Hintergrundsymbol in der Menüleiste nicht als Beweis, dass ein Daemon gesund ist. Teste die schwierigen Fälle: Erzwinge das Beenden der Oberfläche, beende den Dienst, starte während einer aktiven Sitzung neu, aktualisiere zuerst den Client, aktualisiere zuerst den Dienst und entferne ein Credential, während eine Anfrage auf Freigabe wartet. Wenn die Antwort auf einen dieser Fälle «er erholt sich wahrscheinlich» lautet, kennst du das Betriebsverhalten noch nicht.

Die Freigabe gehört zu einem identifizierten Lauf, nicht zu einem gemerkten Rechner

Freigabesysteme scheitern, wenn sie einen vagen Begriff wie «diesen Computer» oder «den aktuellen Benutzer» autorisieren. Autonome Agents starten häufig Unterprozesse, werden nach Änderungen neu gestartet und rufen Tools über Shells auf. Eine Berechtigung, die all diese Aktivitäten umfasst, bedeutet kaum noch etwas.

Binde die Freigabe an einen bestimmten Prozesslauf oder an eine andere Identität, die unabhängiger lokaler Code nicht kopieren kann. Die Freigabeansicht sollte genug Herkunft anzeigen, damit ein Mensch eine Überraschung bemerkt: Die Signatur des ausführbaren Programms, der Befehlspfad und die Anfrageklasse sind bessere Hinweise als ein freundlicher Clientname allein. Einen Prozessnamen kann jeder wählen.

Lege dann die Dauer ausdrücklich fest. Eine Freigabe für eine kurze Agent-Sitzung kann bei wiederholten Aufrufen mit geringem Risiko sinnvoll sein. Sensible Credentials können eine Zustimmung bei jedem Aufruf erfordern. Ein Widerruf muss den identifizierten Lauf sofort stoppen, statt ihn nur in einem Dashboard auszublenden, während seine lokale Verbindung offen bleibt.

Ein Daemon hat hier eine zusätzliche Aufgabe. Er muss eine IPC-Verbindung der Identität zuordnen, die eine Person freigegeben hat, und diese Zuordnung verwerfen, wenn der Client endet oder sich neu verbindet. Ein Client darf niemals allein durch Vorlage einer zwischengespeicherten Kennung eine alte Sitzung fortsetzen. Wenn die Kennung durch eine Datei oder ein Befehlsargument wandern kann, ist sie ein Bearer-Credential mit einem schicken Namen.

Ein Single-Process-Design kann den Freigabestatus neben der aktiven Integration halten und so die Zuordnungsarbeit verringern. Trotzdem muss es einen Agent-Start von einem anderen unterscheiden. Kann die App nicht feststellen, ob eine Anfrage vom freigegebenen Lauf oder von einem späteren Ersatzprozess stammt, sollte sie erneut fragen.

Die sinnvolle Richtlinie ist meist einfacher als erwartet: Bei gesperrtem Tresor ablehnen, bei einem neu identifizierten Lauf einmal fragen und für Credentials, die diese zusätzliche Hürde verdienen, eine individuelle Bestätigung verlangen. Ausgefeilte lokale Richtliniensprachen erzeugen oft Regeln, die unter Druck niemand prüfen kann. Ein kurzer, vorhersehbarer Entscheidungsweg ist leichter zu testen und schwerer versehentlich zu umgehen.

Ein Fehler beim Neustart legt die schwache Stelle offen

Den lokalen Daemon überspringen
Sallyport hält Tresor und Executor in seiner signierten Menüleisten-App, ohne separaten Daemon.

Stell dir einen Entwickler vor, der einem Coding-Agent für einen aktiven Terminal-Lauf gewöhnliche HTTP-Aufrufe freigegeben hat. Das Gateway speichert die Freigabe im Speicher. Der Agent sendet eine Anfrage, und das Gateway beginnt, den ausgehenden Aufruf vorzubereiten. In diesem Moment stürzt die Oberfläche ab oder der Hintergrund-Executor startet nach einem Update neu.

Eine nachlässige Daemon-Implementierung kann die Lage auf mehrere Arten verschlimmern. Der Executor antwortet, bevor er den Sperrstatus des Tresors geladen hat. Sein Client-Socket erscheint wieder unter demselben Pfad. Der Agent verbindet sich erneut. Der Daemon sieht eine zwischengespeicherte Sitzungskennung in der Anfrage und nimmt an, dass die alte Freigabe weiterhin gilt. Gleichzeitig hat der Audit-Schreiber das Protokoll noch nicht wieder geöffnet, sodass der erfolgreiche Wiederholungsversuch keinen dauerhaften Eintrag erhält.

Jede einzelne Entscheidung klingt bequem: Sitzung erhalten, Abfragen reduzieren, schnell neu starten, Protokolle puffern. Zusammen erzeugen sie eine nicht freigegebene Aktion genau in der Zeit, in der der Systemzustand am wenigsten zuverlässig ist.

Das sichere Verhalten ist einfacher. Nach einem Neustart werden flüchtige Freigaben verworfen. Der Tresor bleibt nicht verfügbar, bis sein Schutzstatus bekannt ist. Neue Aktionen werden abgelehnt, bis der Audit-Schreiber einen Eintrag sicher speichern kann. Der Agent erhält eine Ablehnung oder eine vorübergehende Nichtverfügbarkeit. Existiert die Sitzung nicht mehr, ist eine neue Freigabe erforderlich.

Du kannst das ohne besondere Testhardware prüfen:

  1. Öffne eine neue Agent-Sitzung und gib eine erlaubte, wenig riskante Anfrage frei.
  2. Starte eine weitere Anfrage, die an einer Freigabestelle oder einem Testendpunkt wartet.
  3. Beende den Sicherheitsprozess oder Dienst, während die Anfrage wartet.
  4. Starte ihn neu und wiederhole die Anfrage aus dem ursprünglichen Agent-Prozess.
  5. Prüfe, dass eine neue Autorisierung erforderlich ist und das Endergebnis genau einmal im Audit-Eintrag erscheint.

Wiederhole den Test mit einer erneuten Client-Verbindung, einer Gerätesperre, einem entfernten Credential und einem Upgrade. Suche nach veralteter Berechtigung, doppelter Ausführung oder fehlenden Einträgen. Ein Tool, das diese Ergebnisse nicht sichtbar machen kann, ist bei einem Vorfall schwer zu vertrauen.

Audit-Einträge brauchen einen Schreiber, der nicht umgangen werden kann

Anmeldedaten aus Agents heraushalten
Über sp mcp fordern Agents HTTP- und SSH-Aktionen an, ohne konfigurierte Geheimnisse zu erhalten.

Sicherheitsprotokolle halten oft fest, was die Benutzeroberfläche gesehen hat, nicht was der Credential-Executor getan hat. Diese Lücke wird ernst, wenn ein Daemon lokale Anfragen direkt annimmt. Ein kompromittierter Client kann die Oberfläche umgehen, oder die Oberfläche kann abstürzen, nachdem der Executor gehandelt hat.

Führe das Audit-Schreiben auf dem Aktionspfad aus. Die Komponente, die die HTTP-Anfrage sendet oder den SSH-Helfer aufruft, sollte Aufruferidentität, Credential-Referenz, Ziel, Anfrageklasse, Entscheidung und Ergebnis festhalten. Rohe Geheimnisse und Inhalte sollten standardmäßig nicht protokolliert werden. Logs mit Bearer-Tokens werden zu einem zweiten Tresor mit schlechteren Zugriffskontrollen.

Ein einzelner Prozess kann diese Reihenfolge direkt abbilden: prüfen, Entscheidung protokollieren, ausführen und Ergebnis protokollieren. Ein Daemon muss sicherstellen, dass sein eigener Executor keine Anfrage über einen Nebenkanal ausführen kann, der die Protokollierung umgeht. Trenne Protokollierung über IPC und Ausführung nur dann, wenn du das Fehlerverhalten akzeptierst und die Reihenfolge nachweisen kannst.

Manipulationsnachweise sind nach einer Kompromittierung wichtig, nicht nur bei der routinemäßigen Fehlersuche. Kann ein Angreifer eine lokale SQLite-Datei bearbeiten oder ausgewählte Zeilen aus einem Textprotokoll löschen, hilft der Eintrag vielleicht beim Debugging, stellt aber keine vertrauenswürdige Historie dar. Ein append-orientierter Eintrag mit kryptografischer Verkettung gibt Ermittlern die Möglichkeit, Änderungen zu erkennen, vorausgesetzt, die erforderlichen Dateien bleiben erhalten und werden geprüft.

Sallyport leitet Sitzungs- und Aufrufansichten aus einem einzigen verschlüsselten, hash-verketteten Audit-Protokoll ab. Der Befehl sp audit verify prüft die Kette offline, ohne einen Tresorschlüssel zu benötigen. Das löst ein Problem, das getrennte UI- und Daemon-Logs oft erzeugen: zwei Aufzeichnungen, die sich widersprechen, ob eine Aktion stattgefunden hat.

Übertreibe nicht, was ein Audit leisten kann. Eine Kette kann kein Ereignis zurückbringen, dessen Protokollierung ein Angreifer verhindert hat. Sie kann Änderungen innerhalb der erhaltenen Aufzeichnungen erkennen. Das ist trotzdem nützlich, besonders wenn du nach einem Absturz, einem Upgrade oder einem unerwarteten lokalen Client nachträglich eine Abfolge rekonstruieren musst.

Wähle das kleinste Design, das deinen Lebenszyklus erfüllt

Wähle einen einzelnen Prozess, wenn die geschützte Arbeit in Anwesenheit eines Menschen stattfindet, die Anwendung während der Agent-Läufe geöffnet sein kann und weniger lokale Endpunkte wichtiger ist, als unabhängig von der Oberfläche weiterzulaufen. Dieses Layout passt zu einem Credential-Gateway, dessen Hauptversprechen darin besteht, dass eine Person jeden Agent-Lauf sieht und kontrolliert.

Wähle einen Daemon, wenn der Job tatsächlich Dienstkontinuität, die Trennung von einem weniger vertrauenswürdigen Client oder eine eigene Betriebssystemberechtigung benötigt. Verlange für jede hinzugefügte Schnittstelle eine Antwort: Wer verbindet sich, wie identifiziert der Dienst den Aufrufer, welche Anfrage darf er stellen, wann verfällt der Zustand und was geschieht beim Neustart einer der beiden Seiten?

Ein Desktop-Tool wie Sallyport verwendet den Ansatz mit einem einzelnen App-Prozess und einen regulären MCP-Shim für Agent-Anfragen. Sein Tresor führt die HTTP- oder SSH-Aktion selbst aus, sodass der Agent niemals das konfigurierte API- oder SSH-Credential erhält.

Führe vor der Einführung eines der beiden Modelle einen nüchternen Test durch. Beende die Komponente, die die Berechtigung hält, während ein Agent arbeitet, starte sie neu und prüfe, ob die nächste Anfrage abgelehnt, erneut freigegeben und protokolliert wird. Dieser Test verrät mehr über das Design als jedes ausgefeilte Architekturdiagramm.

FAQ

Was ist ein Single-Process-Sicherheitstool für Agents?

Bei einem Single-Process-Design befinden sich Tresor, Freigabeoberfläche, Aktionsausführung und Audit-Protokoll in einem Anwendungsprozess. Bei einem daemonbasierten Design übernimmt ein separater Hintergrundprozess mindestens eine dieser Aufgaben, und Clients kontaktieren ihn über lokale IPC. Keine der beiden Varianten ist automatisch sicherer. Entscheidend sind die offengelegten Schnittstellen und die Frage, wie jeder Prozess nachweist, wer ihn verwenden darf.

Vergrößert ein Sicherheitsdaemon die Angriffsfläche?

Oft ja. Ein Daemon fügt einen Socket, einen Dienstregistrierungspfad, die Verarbeitung von IPC-Nachrichten, die Authentifizierung des Aufrufers und das Verhalten nach Neustarts hinzu. Ein separater Prozess kann trotzdem sinnvoll sein, wenn er eine andere Berechtigungsgrenze braucht oder unabhängig von der Oberfläche weiterlaufen muss. Jede zusätzliche Schnittstelle sollte jedoch begründet sein.

Wie sollte ein Sicherheitsdaemon für Agents lokale Clients authentifizieren?

Ein lokaler Daemon sollte den aufrufenden Prozess authentifizieren und nicht einfach darauf vertrauen, dass die Verbindung vom selben Benutzerkonto kommt. Peer-Anmeldedaten, die Code-Signatur, sofern verfügbar, eingeschränkte Dateisystemrechte und eine ausdrückliche Sitzungsbindung helfen dabei. Der Pfad zu einem Unix-Socket ist kein Autorisierungssystem.

Wo sollten die Anmeldedaten eines AI-Agents gespeichert werden?

Der Tresor sollte Anmeldedaten nur in der Komponente entschlüsseln, die die ausgehende Aktion ausführt. Ein Token über den Agent, eine Umgebungsvariable, eine temporäre Datei oder eine IPC-Antwort zu leiten, macht den Schutz unwirksam, selbst wenn das Token in der Oberfläche maskiert wird.

Wann ist ein daemonbasiertes Design gerechtfertigt?

Ein Daemon ist sinnvoll, wenn ein Hintergrunddienst mehrere Clients überleben, eine Berechtigungsstufe isolieren oder eine gemeinsam genutzte Ressource koordinieren muss, die nicht sicher in jedem Client liegen kann. Er ist nicht sinnvoll, nur weil Hintergrunddienste wichtiger wirken. Das Design muss das IPC-Protokoll und die Prüfungen des Aufrufers dokumentieren.

Wie kann ich die lokale Angriffsfläche eines Agent-Tools untersuchen?

Prüfe den Prozessbaum, lauschende Sockets, Launch-Registrierungen, die Rechte lokaler Sockets und die gespeicherte Dienstkonfiguration. Unter macOS zeigen ps, lsof und launchctl print die meisten beteiligten Komponenten. Prüfe außerdem, was nach einem erzwungenen Beenden, der Abmeldung und einem Neustart geschieht.

Was sollte geschehen, wenn ein Sicherheitsdienst für Agents abstürzt?

Nach einem Absturz sollten sensible Aktionen verweigert werden, bis die Sicherheitskomponente wieder in einem bekannten sicheren Zustand ist. Gefährlich ist eine teilweise Wiederherstellung: Der Executor nimmt Anfragen an, während Freigabestatus, Tresorsperre oder Audit-Schreiber noch nicht wiederhergestellt sind. Teste das, indem du Komponenten während eines echten Aktionsablaufs beendest.

Sind daemonbasierte Tools schwieriger zu warten?

Hintergrunddienste können weiterlaufen, wenn die Oberfläche geschlossen ist, separat aktualisiert werden, veraltete Registrierungen ansammeln und alte Sockets hinterlassen. Ein Single-Process-Programm benötigt weniger Dienstverwaltung, beendet beim Schließen aber auch jede geschützte Aktion. Wähle den Lebenszyklus, den du betreiben und testen kannst, nicht den mit dem eindrucksvolleren Diagramm.

Verbessert die Aufteilung eines Tools auf mehrere Prozesse die Trennung von Berechtigungen?

Nein. Ein separater Daemon isoliert Berechtigungen nur dann, wenn der weniger vertrauenswürdige Prozess ihn nicht zu beliebigen privilegierten Aktionen anweisen kann. Wenn ein Desktop-Client uneingeschränkte Anfragen an einen Dienst mit Root-Rechten senden kann, hat der Daemon das Risiko konzentriert, statt es einzudämmen.

Was sollte ich vor der Einführung eines Credential-Gateways für Agents fragen?

Frage, wo das Geheimnis entschlüsselt wird, welcher lokale Endpunkt Anfragen empfängt, wie der Empfänger den Aufrufer identifiziert, was einen Neustart überlebt und ob das Audit-Protokoll einen Absturz übersteht. Wenn der Anbieter diese Punkte nicht klar beantworten kann, ist die Architektur nicht ausreichend belegt.

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