7 Min. Lesezeit

Zustandslose SSH-Helfer für sicherere KI-Agent-Workflows

Zustandslose SSH-Helfer geben KI-Agenten frische Verbindungen, klarere Auditspuren und weniger übernommene Berechtigungen zwischen Läufen, ohne Risiken auf Remote-Systemen zu verschleiern.

Zustandslose SSH-Helfer für sicherere KI-Agent-Workflows

Autonome Coding-Agenten sollten eine SSH-Sitzung nicht von einem Lauf in den nächsten mitnehmen. Ein neuer lokaler Ausführungskontext für jede Aktion erschwert es einem früheren Lauf, einem späteren unbemerkt Berechtigungen, Identität oder nicht erklärte Nebenwirkungen zu überlassen. Außerdem erhalten Prüfer eine klare Beweseinheit: Dieser Prozess hat diesen Befehl für diesen Host angefordert und der Helfer hat dieses Ergebnis zurückgegeben.

Das macht SSH nicht harmlos. Eine neue Verbindung macht kein Deployment rückgängig, beendet keinen Hintergrundprozess und schützt kein Serverkonto mit viel zu weitreichenden Rechten. Zustandslose Ausführung löst ein engeres, aber sehr praktisches Problem: Sie entfernt lokale Überbleibsel, die Agenten besonders leicht versehentlich ausnutzen.

Zustandslose SSH-Helfer entfernen lokale Überbleibsel, nicht den Zustand auf dem Remote-Host

Ein zustandsloser SSH-Helfer erstellt die für eine Aktion nötige Verbindung, führt die Aktion aus, gibt das Ergebnis zurück und beendet sich, ohne einen authentifizierten Transport für spätere Aufrufe zu bewahren. Die nächste Aktion beginnt wieder mit einem neuen Helferprozess und einem neuen Verbindungsversuch.

Der Unterschied ist wichtig, weil mit «zustandslosem SSH» oft gemeint ist, dass «nirgendwo etwas bestehen bleibt». Das stimmt nicht. SSH bietet mehrere Orte, an denen Zustand gespeichert werden kann:

  • Der Client kann eine Masterverbindung, einen Multiplexing-Socket, einen Known-Hosts-Eintrag, einen Agent-Socket, Konfiguration oder temporäre Dateien behalten.
  • Der Remote-Host kann ein Arbeitsverzeichnis, Shell-Historie, ein hochgeladenes Artefakt, eine Sperrdatei, einen Dienstprozess, einen Paket-Cache und eine geänderte Datenbank behalten.
  • Das Autorisierungssystem kann ein Konto, ein SSH-Zertifikat, einen öffentlichen Schlüssel und Berechtigungen behalten.

Ein zustandsloser Helfer betrifft die erste Kategorie. Er verhindert, dass ein späterer Agent-Aufruf stillschweigend die aktive Verbindung oder den lokalen Zugangskontext eines früheren Aufrufs übernimmt. Die Gegenseite bleibt ein echter Computer mit echten Folgen.

Darum ist «neue Verbindung» die bessere operative Bezeichnung als «neuer Server». Der Helfer ist neu. Der Server ist es nicht.

Angenommen, ein Agent führt eine Deployment-Prüfung aus und beendet sich, nachdem ein Prüfer seine nächste vorgeschlagene Änderung abgelehnt hat. Wenn der erste Lauf einen Multiplexing-Socket hinterlassen hat, kann sich ein anderer Prozess auf demselben Rechner an einen bereits authentifizierten Kanal anhängen. Der nächste Prozess hat damit eine Sicherheitsgrenze übersprungen, die Betreiber eigentlich pro Lauf vorgesehen hatten. Bei einem zustandslosen Helfer muss dieser zweite Prozess eine neue Aktion anfordern und erneut den vorgesehenen Autorisierungsweg durchlaufen.

Der Vorteil betrifft teilweise die Sicherheit und teilweise die Diagnose. Sieht ein Incident-Prüfer eine gemeinsam genutzte Verbindung, die stundenlang bestand, muss er rekonstruieren, welche von mehreren Prozessen sie verwendet haben. Wenn jede Anfrage ihren eigenen Verbindungslebenszyklus besitzt, hat der Datensatz einen natürlichen Anfang und ein natürliches Ende.

Das Teilen von Verbindungen erschwert die Zuordnung auf Laufebene

OpenSSH unterstützt bewusst das Teilen von Verbindungen. Das Handbuch zu ssh_config beschreibt ControlMaster als Möglichkeit, mehrere Sitzungen über eine Netzwerkverbindung zu teilen. ControlPersist kann die Masterverbindung nach dem Ende der Clients im Hintergrund offen halten. Diese Optionen sind praktisch für Administratoren, die mehrere Befehle aus einem Terminal ausführen. Für Agent-Läufe, die getrennte Berechtigungen und getrennte Aufzeichnungen brauchen, sind sie jedoch kein guter Standard.

Eine häufige Konfiguration sieht so aus:

Host build-box
  HostName 10.0.0.24
  User deploy
  ControlMaster auto
  ControlPath ~/.ssh/cm-%r@%h:%p
  ControlPersist 15m

Der erste SSH-Aufruf erstellt unter ~/.ssh einen authentifizierten Master-Socket. Spätere Aufrufe, die auf diesen Socket zugreifen können, dürfen die Verbindung während des fünfzehnminütigen Aufbewahrungszeitraums wiederverwenden. Ein Agent-Prozess, der nach dem Ende des ursprünglichen Prozesses gestartet wird, kann in seinem eigenen Protokoll wie eine unabhängige Verbindung aussehen, obwohl er tatsächlich einen früher eingerichteten Transport verwendet.

Das führt zu vier unterschiedlichen Problemen.

Erstens verschiebt sich die Bedeutung einer Genehmigung. Wenn eine Person einen bestimmten Agent-Prozess für eine Prüfung freigegeben hat, sollte diese Genehmigung nicht automatisch für einen neuen Prozess gelten, der zufällig denselben Socket findet.

Zweitens lässt sich die Identität des Ziels zum entscheidenden Zeitpunkt schwerer prüfen. Die SSH-Hostprüfung findet statt, wenn die Masterverbindung aufgebaut wird. Spätere Clients übernehmen dieses Ergebnis. Ein Prüfer, der einen späteren Aufruf untersucht, muss ein älteres Verbindungsereignis finden, um zu wissen, welche Hostprüfung stattgefunden hat.

Drittens verlieren Protokolle die einfache Beziehung zwischen Anfrage und Transport. Ein herkömmliches SSH-Serverprotokoll kann eine Anmeldung aufzeichnen, während Aufzeichnungen auf Anwendungsebene viele Befehle zeigen. Beides kann korrekt sein, aber die Zuordnung wird genau dann zur Arbeit, wenn niemand dafür Zeit hat.

Viertens wird der Socket selbst zu einem schützenswerten Objekt. OpenSSH warnt in ssh_config, dass jeder, der auf den Control-Socket zugreifen kann, auch auf die Verbindung zugreifen kann. Dateiberechtigungen helfen, machen einen gemeinsamen authentifizierten Kanal aber nicht passend für einen feindlichen oder einfach nur verwirrten Arbeitsbereich.

Deaktiviere Multiplexing für Aufrufe, die eine klare Zuordnung brauchen. Ein direkter Aufruf kann diese Entscheidung ausdrücklich festlegen:

ssh -o ControlMaster=no -o ControlPath=none deploy@build-box 'id; hostname'

Die erwartete Ausgabe hat beispielsweise diese Form:

uid=1004(deploy) gid=1004(deploy) groups=1004(deploy)
build-box

Der Befehl beweist nur, welches Konto und welcher Host geantwortet haben. Er beweist nicht, dass das Konto passende Rechte hatte oder dass die angeforderte Aufgabe sicher war. Trotzdem kann ein Prüfer damit eine Aktion einem Verbindungsversuch zuordnen.

Verwechsle eine fehlende ControlMaster-Zeile nicht mit einer vollständigen Lösung. Eine globale SSH-Konfiguration kann sie setzen, ein Wrapper kann sie hinzufügen und ein Prozess kann ControlPath auf einen unerwarteten Ort zeigen lassen. Die Ausführungsgrenze sollte ihre SSH-Optionen selbst festlegen, statt den Dotfiles des Repositorys zu vertrauen.

Jeder Agent-Lauf braucht seine eigene Berechtigungsgrenze

Ein Agent-Lauf ist keine menschliche Terminalsitzung mit schnellerem Tippen. Er kann neue Anweisungen aus Issues, Pull Requests, generierten Testergebnissen, kopiertem Logtext und Quelldateien erhalten, die er nicht selbst erstellt hat. Jeder dieser Inhalte kann ihn zu Befehlen lenken, die nicht Teil der ursprünglichen Absicht waren.

Dadurch verändert sich die Bedeutung von Komfortfunktionen. Eine Person, die eine Sitzung offen hält, weiß normalerweise, dass sie sie offen hält. Ein Agent kann eine spätere Aufgabe starten, ohne zu wissen, dass ein alter Kanal weiterhin verfügbar ist. Seine Werkzeugschnittstelle zeigt oft nur «Befehl ausführen», während der Client im Hintergrund einen Socket findet und frühere Berechtigungen übernimmt.

Behandle den Agent-Prozess als Einheit, die eine Genehmigung erhält. Wenn er endet, sollte auch sein Zugriff enden. Startet ein neuer Prozess, selbst wenn derselbe Editor oder Orchestrator ihn startet, fordere eine neue Autorisierungsentscheidung, bevor er einen geschützten Host erreicht.

Dieser Ansatz ist anfangs strenger, als viele Entwickler möchten. Wiederholte Genehmigungen wirken lästig und führen schnell zu einer großzügigen Allowlist. Damit verschwindet jedoch genau die nützliche Grenze. Besser ist es, zusammengehörige Aktionen zu einem ausdrücklichen Lauf zu bündeln, diesem Lauf nach Prüfung seiner Identität Zugriff zu geben und den Zugriff mit seinem Ende zu entziehen.

Die Codesignatur-Identität ist hier wichtig, beantwortet aber nicht jede Frage. Sie kann einem Prüfer sagen, welches signierte Programm den Prozess gestartet hat. Sie sagt nicht, ob das Programm vertrauenswürdige Anweisungen verarbeitet oder ob das aktuelle Repository eine bösartige Aufforderung enthält. Eine Genehmigung sollte einen bekannten Prozess an einen begrenzten Zeitraum mit Berechtigungen binden, nicht jede Anweisung absegnen, die dieser Prozess jemals liest.

Eine klare Grenze behandelt auch Wiederholungen richtig. Ein Netzwerkfehler kann eine neue Anfrage auslösen. Das Gateway sollte protokollieren, dass die erste Aktion vor der Ausführung oder während des Transports fehlgeschlagen ist, und die Wiederholung als weitere Aktion protokollieren. Werden Wiederholungen in einem vagen Erfolgsdatensatz zusammengefasst, fehlen Informationen, die Incident-Teams brauchen.

Agent-Forwarding hebelt die Grenze für Zugangsdaten aus

SSH-Agent-Forwarding gibt einem Remote-Host die Möglichkeit, deinen lokalen Authentifizierungsagenten zum Signieren von Prüfungen aufzufordern. Die private Schlüsseldatei wird zwar nicht auf den Host kopiert, aber dieser Unterschied klingt oft sicherer, als er ist.

Das OpenSSH-Handbuch zu ssh warnt, dass Benutzer, die Dateiberechtigungen auf dem Remote-Host umgehen können, auf den weitergeleiteten Agenten zugreifen können. Ein Root-Benutzer auf diesem Host kann den weitergeleiteten Socket nutzen, um sich während der offenen Verbindung an anderer Stelle zu authentifizieren. Das private Schlüsselmaterial erhält er weiterhin nicht, aber er kann die dahinterliegende Berechtigung verwenden. Für einen autonomen Agenten ist das meist genau das Risiko, das du vermeiden wolltest.

Vermeide Aufrufe wie diesen:

ssh -A deploy@build-box 'git fetch && ./deploy.sh'

Das Flag -A leitet den lokalen Authentifizierungsagenten weiter. Ein Deployment-Skript, das einen zweiten Rechner erreicht, kann den Remote-Host dann dazu bringen, über den weitergeleiteten Socket Signaturen anzufordern. Ein kompromittierter Build-Rechner oder ein von einem nicht vertrauenswürdigen Mitwirkenden geändertes Skript erhält dadurch einen unerwarteten Weg in eine andere Umgebung.

Verwende stattdessen ein Zugangsmittel, das zur Aufgabe auf dem Ziel gehört. Das kann ein Deployment-Konto mit einem eingeschränkten öffentlichen Schlüssel, ein kurzlebiges SSH-Zertifikat für eine Umgebung oder ein Remote-Servicekonto sein, das nur das benötigte Artefakt abrufen darf. Der genaue Mechanismus hängt von deiner Infrastruktur ab. Die Regel bleibt gleich: Verwandle die genehmigte Aktion eines Agenten nicht in allgemeinen Authentifizierungszugriff von einem Remote-Rechner aus.

Manche Teams behalten Forwarding bei, weil verschachtelte SSH-Verbindungen praktisch sind. Sie haben einen Bastion-Host und springen anschließend zu privaten Hosts weiter. Verwende nach Möglichkeit ProxyJump oder eine streng kontrollierte Gateway-Route. Dabei behält der Client die Kontrolle über den Verbindungsaufbau, statt einen mächtigen lokalen Agent-Socket auf dem Zwischenhost abzulegen.

Auch Portweiterleitungen verdienen Misstrauen. Lokale, Remote- und dynamische Weiterleitungen können aus einem genehmigten Befehl einen offenen Tunnel machen, der länger besteht als die eigentliche Aktion. Ein zustandsloser Helfer sollte Weiterleitungsfunktionen ablehnen oder gesondert genehmigen lassen, sofern die konkrete Aufgabe sie nicht benötigt.

Ein präzises Remote-Konto begrenzt den Schaden schlechter Anweisungen

Sensible Schlüssel pro Aufruf schützen
Fordere für jede Verwendung von SSH-Schlüsseln mit Einzelgenehmigung Touch ID oder einen Klick an.

Ein frischer lokaler Zustand hilft nicht, wenn der Remote-Login alles darf. Das Konto, das ein Agent erreicht, sollte eine klar beschriebene Aufgabe und passende Berechtigungen haben.

Auf einem Deployment-Host kann das ein Konto sein, das einen Release-Symlink umschalten, einen bestimmten Dienst neu starten und ein Deployment-Verzeichnis lesen darf. Es sollte nicht zusätzlich uneingeschränkte passwortlose Rechteausweitung, Zugriff auf die Home-Verzeichnisse aller Benutzer und Berechtigung zum Ändern des CI-Runners besitzen. Solche Kombinationen entstehen, weil eine Automatisierungsaufgabe vor dem Mittagessen funktionieren sollte. Sie bleiben bestehen, weil später niemand die Rechte einschränkt.

OpenSSH bietet Serverbetreibern im Format von authorized_keys mehrere Kontrollen. Das Handbuch dokumentiert unter anderem command=, womit bei der Authentifizierung durch den Schlüssel ein bestimmter Befehl erzwungen wird, sowie Optionen zum Deaktivieren von Port-Forwarding, X11-Forwarding und Agent-Forwarding. Diese Kontrollen sind nützlich, wenn das Ziel nur eine kleine, stabile Befehlsschnittstelle braucht.

Ein Betriebsteam kann beispielsweise einen eigenen öffentlichen Schlüssel an einen eingeschränkten Remote-Wrapper binden:

command="/usr/local/libexec/release-action",no-port-forwarding,no-X11-forwarding,no-agent-forwarding ssh-ed25519 AAAA... agent-release

Der erzwungene Befehl sollte angeforderte Argumente defensiv verarbeiten. Übergebe keinen unveränderten Benutzereingabetext an eine Shell. Ein sicherer Wrapper akzeptiert eine kleine Menge von Verben, prüft Release-IDs gegen ein erwartetes Format, schreibt einen Audit-Datensatz und führt die passende festgelegte Aktion aus. Wenn der Agent beliebigen Shell-Zugriff braucht, sollte das offen ausgesprochen werden. Begrenze dann die Berechtigungen des Kontos so weit, dass dieses Risiko vertretbar bleibt.

Ein erzwungener Befehl ist keine allgemeine Policy-Sprache. Er ist eine bewusst kleine Schnittstelle auf einem Host. Genau diese Begrenzung ist seine Stärke. Du kannst sie testen, prüfen und feststellen, welche Aktionen sie ausführen kann, ohne einen Stapel natürlichsprachiger Regeln interpretieren zu müssen.

Sei vorsichtig mit sudo. Eine Zeile, die ein Skript erlaubt, kann trotzdem zu weitreichendem Zugriff werden, wenn das Skript beliebige Pfade akzeptiert, Konfiguration aus einem beschreibbaren Verzeichnis lädt, einen Editor aufruft oder ein anderes Programm über eine vom Benutzer kontrollierte Umgebungsvariable startet. Prüfe die gesamte Aufrufkette. Die Berechtigungszeile ist der Beginn der Prüfung, nicht ihr Ende.

Der Aktionsdatensatz sollte beantworten, wer, was, wo und mit welchem Ergebnis

Ein nützliches Auditprotokoll muss mehr aussagen als nur, dass SSH verwendet wurde. Eine Person sollte eine Aktion rekonstruieren können, ohne zu raten, zu welchem Agent-Lauf sie gehörte.

Protokolliere die Kennung des Agent-Laufs, seine Prozessberechtigung, die Entscheidung des Prüfers, Ziel, Remote-Konto, angeforderten Befehl oder Vorgang, Zeitpunkt, Ergebnis und einen Verweis auf die Ausgabe. Halte die aufgelöste Host-Identität fest, wenn dein Design sie zugänglich machen kann. Protokolliere auch eine Ablehnung. Eine abgelehnte Aktion zeigt, dass die Grenze funktioniert hat, und kann eine falsche Anweisung aufdecken, bevor Schaden entsteht.

Befehle brauchen besondere Behandlung. Der unveränderte Befehl kann Passwörter, Zugriffstoken, Abfragewerte und private Pfade enthalten. Alles zu schwärzen macht den Datensatz unbrauchbar, alles zu behalten kann das Protokoll in einen weiteren Geheimnisspeicher verwandeln. Die praktische Antwort besteht darin, die Aktionsschnittstelle so zu gestalten, dass sensible Werte gar nicht erst als Argumente erscheinen. Wenn eine Schwärzung nötig ist, protokolliere sowohl das Ereignis als auch genügend strukturierte Informationen, um den Vorgang zu identifizieren.

Für die Ausgabe gilt dasselbe. Ein Fehler aus einem Deployment-Befehl kann eine Umgebungsvariable oder eine URL mit Zugangsdaten ausgeben. Halte die Ausgabe getrennt vom Kerndatensatz, beschränke den Lesezugriff und behandle sie als potenziell sensible Eingabe für den nächsten Agent-Lauf. Gib nicht automatisch ein vollständiges Produktionsprotokoll an einen Agenten zurück, nur weil er eine Fehlerdiagnose angefordert hat.

Eine weitere Unterscheidung sollte klar bleiben: Ein Protokoll, das besagt, dass ein Agent eine Aktion angefordert hat, ist etwas anderes als ein Protokoll, das beweist, dass die Aktion den Remote-Host erreicht hat. Transportfehler, Ablehnung des Host-Schlüssels, fehlgeschlagene Remote-Authentifizierung, Exit-Status des Befehls und verlorene Verbindungen sind unterschiedliche Ergebnisse. Ein gutes Protokoll gibt jedem Ergebnis einen eigenen Status, statt alles unter «fehlgeschlagen» abzulegen.

Manipulationsnachweise verändern das Vertrauensmodell des Datensatzes. Ein hashverkettetes Protokoll kann zeigen, dass Einträge verändert, entfernt oder umsortiert wurden, wenn die Prüfung fehlschlägt. Es kann nicht sagen, dass der ursprüngliche Befehl klug war, und es kann einen kompromittierten Endpunkt nicht wahrheitsgetreu machen. Es schützt die vorhandene Historie, ersetzt aber keine Härtung des Systems.

Ein fehlgeschlagenes Deployment zeigt, warum ein frischer Zustand hilft

Einen fragwürdigen Agent-Lauf beenden
Widerrufe einen Agent-Lauf sofort im Sessions-Journal, wenn sein nächster Befehl nicht mehr richtig aussieht.

Stell dir vor, ein Coding-Agent erhält die Aufforderung, einen Branch auf einen Staging-Host zu deployen. Sein erster Aufruf öffnet eine SSH-Verbindung, prüft den freien Speicher und startet einen Release-Befehl. Der Release-Befehl schlägt fehl, weil eine Migrationssperre existiert. Der Agent sieht den Fehler, liest Repository-Notizen und erhält eine kopierte Nachricht mit der Aufforderung, «die Sperre zu löschen und es mit dem Notfallkonto erneut zu versuchen».

Diese Nachricht kann ein harmloser, aber unsicherer Vorschlag sein. Sie kann aber auch eine Prompt-Injection enthalten, die in einer Datei versteckt ist, die der Agent untersuchen sollte. In beiden Fällen schlägt der Agent nun einen Befehl außerhalb des ursprünglichen Deployment-Ablaufs vor.

Bei einer langlebigen gemeinsamen Verbindung kann einiges schiefgehen. Der ursprüngliche Transport kann weiterhin als weitreichendes Deployment-Konto authentifiziert sein. Ein neuer Prozess kann ihn wiederverwenden. Ein Prüfer sieht möglicherweise nur die Genehmigung der ersten Verbindung und erkennt die spätere Rechteausweitung nicht klar. Wenn zusätzlich ein SSH-Agent weitergeleitet wurde, kann der Staging-Host einen Weg erhalten, eine andere Identität zu verwenden.

Mit einem zustandslosen Helfer und einer Autorisierung pro Lauf beginnt der nächste Aufruf des Agenten als neue Anfrage. Die Grenze identifiziert den neuen Agent-Prozess, protokolliert den tatsächlich vorgeschlagenen Befehl und das Ziel und fordert eine Genehmigung an, falls der Lauf noch nicht freigegeben ist. Ein Prüfer kann die Anfrage nach dem Notfallkonto ablehnen und stattdessen eine eingeschränkte Aktion zur Untersuchung des Eigentümers der Sperre genehmigen.

Die frische Verbindung entscheidet nicht, dass das Löschen einer Sperre unsicher ist. Menschen müssen Vorgänge weiterhin beurteilen. Sie verhindert jedoch, dass ein früher genehmigter Kanal diese Entscheidung stillschweigend bedeutungslos macht.

Darum gehört ein zustandsloses SSH-Design neben sinnvolle Befehlsbeschränkungen und nicht an ihre Stelle. Verbindungsisolation begrenzt übernommene lokale Berechtigungen. Eine eingeschränkte Remote-Schnittstelle begrenzt, was eine neue Verbindung tun kann. Audit-Datensätze helfen Menschen später, beide Entscheidungen zu verstehen.

Zustandslose Ausführung braucht ein ausdrückliches Betriebskonzept

Ergebnisse zurückgeben, keine Zugangsdaten
Sallyport führt den angeforderten SSH-Befehl selbst aus und gibt Ergebnisse zurück, ohne Zugangsdaten an den Agenten zu übergeben.

Ein Helfer, der für jede Anfrage eine Verbindung öffnet, braucht klare Regeln für Hostprüfung, Zeitüberschreitungen, Abbruch und Fehlerberichte. Werden diese Details der jeweiligen Agent-Umgebung überlassen, entsteht versteckter Zustand unter einem anderen Namen.

Prüfe Host-Schlüssel. StrictHostKeyChecking=yes weist OpenSSH an, Hosts mit unbekanntem oder geändertem Schlüssel abzulehnen, statt interaktiv nachzufragen. Für eine geschützte automatisierte Aktion ist das normalerweise die richtige Einstellung. Stelle vertrauenswürdige Host-Schlüssel über einen kontrollierten Prozess bereit und brich ab, wenn das Ziel nicht übereinstimmt.

Verwende begrenzte Zeitüberschreitungen. Eine blockierte SSH-Verbindung sollte nach einer bestimmten Zeit einen protokollierten Fehler zurückgeben und nicht unbegrenzt als halbfertige Sitzung verfügbar bleiben. Der Helfer sollte bei einem Abbruch auch untergeordnete Prozesse beenden, soweit das Betriebssystem dies erlaubt, und melden, ob die Beendigung bestätigt werden kann. Melde einen Remote-Befehl nicht als abgebrochen, wenn der Transport erst verloren ging, nachdem der Server ihn bereits gestartet hatte.

Halte die Form der Anfrage klein und prüfbar. Eine Aktionsgrenze kann eine SSH-Anfrage mit strukturierten Feldern wie Ziel, Konto, Befehl, sofern unterstützt Arbeitsverzeichnis und Zeitüberschreitung darstellen. Sie sollte keinen Block von Shell-Konfiguration akzeptieren, der Identitätsdateien, Proxy-Verhalten, Pfade zu Control-Sockets und Weiterleitungsoptionen ohne Prüfung verändert.

Ein Gateway kann den SSH-Schlüssel halten, während der Agent eine Aktion anfordert. Sallyport folgt diesem Modell für SSH mit dem enthaltenen zustandslosen sp-ssh-Helfer: Der Agent erhält den SSH-Schlüssel nicht, und die App führt die Aktion aus.

Die Grenze sollte außerdem zwischen einer Sitzungsfreigabe und einer Genehmigung pro Aufruf unterscheiden. Eine Sitzungsfreigabe passt zu einem begrenzten Agent-Lauf, bei dem ein Prüfer eine erwartete Abfolge von Arbeiten akzeptiert. Eine Genehmigung pro Aufruf passt zu Zugangsdaten oder Zielen, bei denen jede Verwendung eine eigene menschliche Entscheidung verdient. Tu nicht so, als böten diese Optionen dieselbe Kontrolle. Sie tauschen bewusst Unterbrechung gegen Granularität.

Prüfe auf verborgene Wiederverwendung, bevor du der Grenze vertraust

Du kannst testen, ob deine Einrichtung tatsächlich unabhängige Verbindungen erstellt. Führe den Test in einer Nicht-Produktionsumgebung mit einem Konto ohne sensible Zugriffsrechte aus.

Starte zunächst zwei getrennte Agent- oder Helferprozesse, die jeweils einen harmlosen Befehl wie id ausführen. Prüfe das Authentifizierungsprotokoll des SSH-Servers und dein Aktionsprotokoll. Du solltest zwei Verbindungsversuche sehen, die sich zwei getrennten Prozessdatensätzen zuordnen lassen.

Untersuche anschließend die Clientseite auf Multiplexing-Sockets. Auf macOS und Linux-ähnlichen Systemen kann eine grobe Prüfung so aussehen:

find ~/.ssh -type s -print

Wenn ein Pfad erscheint, der zu einem Control-Socket gehört, ermittle, welche Konfiguration ihn erstellt hat. Lösche einen Socket auf einem gemeinsam genutzten Rechner nicht blind. Ermittle zuerst seinen Besitzer und die aktiven Clients. Entferne Einstellungen für das Teilen von Verbindungen aus dem Ausführungspfad des isolierten Helfers, statt dich auf eine nachträgliche Bereinigung zu verlassen.

Führe schließlich eine genehmigte Aktion aus, beende den Agent-Prozess und starte einen zweiten Prozess. Der zweite Prozess sollte weder die Genehmigung noch den Authentifizierungstransport des ersten Prozesses oder die Möglichkeit übernehmen, ohne eine neue Entscheidung eine Remote-Shell aufzurufen. Teste den abgelehnten Pfad genauso sorgfältig wie den genehmigten. Teams stellen oft fest, dass der Erfolgsweg isoliert ist, während ein Fehlerbehandler auf einen direkten SSH-Befehl zurückfällt.

Diese letzte Prüfung entdeckt den bekannten Fehler: Ein sorgfältiges Gateway verarbeitet normale Anfragen, aber ein Wiederholungsskript oder Diagnosewerkzeug umgeht es, sobald der Druck steigt. Der Umgehungsweg wird meist von jemandem ergänzt, der den Dienst schnell wiederherstellen will. Danach wird er zum Weg, den ein Agent findet, wenn sein erster Versuch fehlschlägt.

Ein frischer Zustand für jede SSH-Aktion ist keine Formsache. Er gibt autonomer Arbeit eine Grenze, die Menschen prüfen, genehmigen, widerrufen und untersuchen können. Halte das Remote-Konto klein, lehne weitergeleitete Zugangsdaten ab, protokolliere Ergebnisse präzise und sorge dafür, dass jeder neue Agent-Prozess seinen eigenen Zugriff erhält.

FAQ

Was ist ein zustandsloser SSH-Helfer?

Ein zustandsloser Helfer startet für jede angeforderte SSH-Aktion einen neuen lokalen Ausführungskontext und verwirft ihn, sobald die Aktion endet. Er sollte weder eine SSH-Masterverbindung noch eine wiederverwendbare Remote-Shell, einen weitergeleiteten Agent-Socket oder ein privates Zugangsmittel im eigenen Agent-Prozess behalten. Der entfernte Rechner kann weiterhin Dateien und Prozesse behalten. Zustandslosigkeit beseitigt daher keine Folgen auf dem Server.

Machen zustandslose SSH-Abläufe Agent-Workflows zu langsam?

In der Regel nicht. Eine neue Verbindung verursacht zusätzlichen Aufwand für Authentifizierung und Einrichtung. Die meisten Agent-Aktionen sind jedoch begrenzte Verwaltungsbefehle, Deployments oder Prüfungen und keine tausenden winzigen interaktiven Vorgänge. Wenn der Verbindungsaufbau den größten Teil deiner Arbeitslast ausmacht, reduziere die Zahl der geplanten Aktionen oder verwende eine eng begrenzte Schnittstelle auf der Serverseite, statt stillschweigend einen Control-Socket zu teilen.

Sollten KI-Agenten SSH ControlMaster verwenden?

Nein. ControlMaster erlaubt späteren SSH-Clients, eine vorhandene Masterverbindung wiederzuverwenden. Dadurch übernehmen diese Aufrufe eine Verbindung, die von einem anderen Prozess erstellt wurde. Für eine kurze Terminal-Sitzung einer Person kann das sinnvoll sein. Für Agent-Prozesse schwächt es jedoch die Zuordnung auf Laufebene und vergrößert die Auswirkungen eines kompromittierten oder verwirrten Prozesses.

Setzt eine neue SSH-Verbindung den Remote-Server zurück?

Ein Remote-Befehl kann einen laufenden Prozess, einen veränderten Arbeitsbaum, temporäre Dateien, geänderte Berechtigungen oder einen modifizierten Dienst hinterlassen. Behandle jeden Aufruf lokal als isoliert und mache den Zustand auf der Gegenseite ausdrücklich: Verwende Befehlsargumente, geprüfte Revisionen, benannte Deployment-Verzeichnisse und Aufräumregeln. Versprich nicht, dass eine neue SSH-Verbindung den Rechner zurücksetzt.

Warum ist die Wiederverwendung von SSH-Verbindungen für autonome Agenten riskant?

Die Wiederverwendung von SSH-Verbindungen ist praktisch, weil sie erneute Authentifizierung und Handshake-Arbeit vermeidet. Sie macht die Sicherheitslage unklarer, wenn mehrere Agent-Läufe über denselben authentifizierten Transport handeln können, besonders wenn der gemeinsame Socket zu großzügige Berechtigungen hat oder nach dem Ende des ursprünglichen Laufs bestehen bleibt. Die richtige Wahl hängt davon ab, ob schnelle interaktive Nutzung oder nachvollziehbare Automatisierung wichtiger ist.

Wie begrenze ich das Remote-Konto eines KI-Agenten?

Verwende ein Konto mit genau den Berechtigungen, die die Aufgabe benötigt, begrenze die erreichbaren Hosts und verhindere nach Möglichkeit eine uneingeschränkte interaktive Nutzung. Die Optionen von SSHs authorized_keys, ein erzwungener Befehl oder ein eigener Remote-Wrapper können den Zweck des Kontos begrenzen. Ein zustandsloser Client gleicht kein Konto aus, das alle Produktionsgeheimnisse lesen kann.

Ist SSH-Agent-Forwarding für Coding-Agenten sicher?

Vermeide die Weiterleitung, sofern die Aufgabe nicht ohne sie funktioniert. OpenSSH dokumentiert, dass ein weitergeleiteter Agent dem Remote-Host erlaubt, über deinen lokalen Agenten Signaturen anzufordern. Ein Root-Benutzer auf dem Remote-Host kann häufig auf diesen weitergeleiteten Socket zugreifen. Gib dem Agenten stattdessen ein zweckgebundenes Zugangsmittel auf der Zielseite.

Was sollte ein SSH-Auditprotokoll für einen KI-Agenten enthalten?

Protokolliere den aufrufenden Agent-Prozess, die genehmigte Identität oder Berechtigung, Ziel, Konto, Befehl oder Anfrage, Zeitstempel, Exit-Status und jede Genehmigungsentscheidung. Schütze die Befehlsausgabe, denn sie enthält oft das nächste Problem, darunter versehentlich auch Geheimnisse. Ein unveränderlich angehängtes Protokoll ist stärker als eine veränderbare Textdatei, ersetzt aber keine Prüfung.

Kann zustandsloses SSH vor einem kompromittierten Server schützen?

Eine zustandslose lokale Ausführung hilft, weil jeder Aufruf ohne wiederverwendbaren lokalen Transport und ohne verborgene Sitzungseinrichtung beginnt. Sie verhindert jedoch nicht, dass der Remote-Server bösartig, kompromittiert oder überprivilegiert ist. Prüfe Host-Schlüssel, beschränke Zielkonten und leite Zugangsdaten nicht an Hosts weiter, denen du nicht vertraust.

Wann sollte ein KI-Agent statt direktem SSH ein SSH-Gateway verwenden?

Verwende ein Gateway, wenn Agenten auf Systeme mit echten Zugangsdaten zugreifen müssen und eine Person den Zugriff genehmigen oder ein dauerhaftes Aktionsprotokoll prüfen soll. Ein direkter SSH-Befehl kann für eine kurzlebige Sandbox mit einem unkritischen Konto ausreichen. Der Produktionszugriff braucht eine Grenze, die der Agent aus seinem eigenen Arbeitsbereich heraus nicht umschreiben kann.

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