8 Min. Lesezeit

HTTP oder SSH für KI-Agenten: Schadensumfang begrenzen

Wähle HTTP oder SSH für KI-Agenten, indem du Berechtigungen, Audit-Nachweise, Sicherheit bei Wiederholungen und Fehlerszenarien vergleichst, die kleine Aufgaben in weitreichenden Zugriff verwandeln können.

HTTP oder SSH für KI-Agenten: Schadensumfang begrenzen

Ein KI-Agent sollte HTTP verwenden, wenn ein Dienst die beabsichtigte Aktion als eng begrenzten, authentifizierten Vorgang ausdrücken kann. SSH sollte er nur verwenden, wenn die Aufgabe eine Fähigkeit auf Maschinenebene braucht, die eine API nicht anbietet, und dann ausschließlich über ein Konto und eine Befehlsschnittstelle, die genau für diese Aufgabe ausgelegt sind.

Der häufigste Fehler besteht darin, beide Übertragungswege so zu vergleichen, als wäre einer modern und der andere veraltet. Das geht an der eigentlichen Entscheidung vorbei. HTTP und SSH sind Transportmechanismen. Die damit verbundenen Rechte, die akzeptierten Eingaben und die aufbewahrten Nachweise entscheiden darüber, ob ein Agent eine begrenzte Änderung vornehmen kann oder mit Administratorrechten durch einen Produktivhost wandert.

Ich habe Teams erlebt, die einen angeblich vorübergehenden SSH-Schlüssel ausstellten, weil ein Agent eine einzige betriebliche Information brauchte. Einen Monat später konnte der Schlüssel Deployment-Geheimnisse lesen, interne Dienste erreichen und eine interaktive Shell starten. Niemand hatte eine dramatische Sicherheitsentscheidung getroffen. Man hatte nur eine bequeme Voreinstellung akzeptiert. Genau so bekommt eine kleine Aufgabe einen großen Schadensumfang.

Die Schnittstelle bestimmt die Rechte des Agenten

HTTP oder SSH für KI-Agenten ist eine Frage der Form der Fähigkeiten, nicht der Vorliebe für ein Protokoll. Ein HTTP-Aufruf kann weitreichend und gefährlich sein, während eine SSH-Verbindung streng begrenzt werden kann. In der Praxis bieten APIs jedoch häufiger eine brauchbare Möglichkeit, Rechte zu beschränken, weil Endpunkt, Methode, Anfrageschema und Token-Berechtigung gemeinsam einen einzelnen Vorgang beschreiben können.

Nimm die Anweisung: einen ausgefallenen Worker neu starten. Ein HTTP-Endpunkt wie POST /workers/worker-17/restart nennt Ziel und erlaubte Methode. Der Dienst kann einen unbekannten Worker ablehnen, eine Rolle mit Neustartberechtigung verlangen und einen mit dem Token verknüpften Datensatz schreiben. Ein Shell-Befehl wie ssh host sudo systemctl restart worker bringt eine deutlich umfassendere implizite Berechtigung mit. Er setzt voraus, dass Konto, sudo-Konfiguration, Regeln für Unit-Namen, Shell-Parsing und Hostzustand korrekt sind.

Das macht die API nicht automatisch sicher. Ein Token, das jeden Endpunkt aufrufen, weitere Tokens erstellen oder alle Datensätze exportieren kann, hat hinter einer übersichtlichen URL einen großen Schadensumfang. Umgekehrt kann ein erzwungener SSH-Befehl, der eine feste Worker-ID aus einer Allowlist akzeptiert, enger begrenzt sein als eine schlecht entworfene administrative API.

Führe vor der Verbindung eines der beiden Werkzeuge diesen Test durch: Beschreibe die kleinste erfolgreiche Aktion in einem Satz und liste anschließend auf, was dieselben Zugangsdaten noch tun können, wenn der Agent unerwartete Eingaben erzeugt. Wenn du den zweiten Teil nicht erklären kannst, hast du die tatsächlichen Rechte noch nicht gemessen.

Eine enge Schnittstelle hat vier Eigenschaften:

  • Sie nennt eine kleine Menge von Zielen statt einer ganzen Umgebung.
  • Sie akzeptiert strukturierte Eingaben mit einer überprüfbaren Grammatik.
  • Sie lehnt benachbarte Aktionen ab, die die aktuelle Aufgabe nicht benötigt.
  • Sie erzeugt einen Datensatz, mit dem eine andere Person das Ergebnis später erklären kann.

Auch die Lebensdauer der Zugangsdaten sollte sich nach der Aufgabe richten. Zugangsdaten für einen einzigen Lauf dürfen nicht stillschweigend zu dauerhaftem Zugriff werden, weil niemand daran gedacht hat, sie zu entfernen. Die Lebensdauer des Prozesses ist eine bessere Grenze als eine Erinnerung im Kalender.

HTTP bietet nur dann sinnvolle Grenzen, wenn die API sie durchsetzt

HTTP verringert den Schadensumfang eines Agenten, wenn der Dienst die Autorisierung auf Ressourcen- und Vorgangsebene prüft. Ein Bearer-Token ist nur ein Träger. Seine Sicherheit hängt davon ab, was der Server nach dem Empfang des Tokens überprüft.

RFC 9110 beschreibt HTTP-Methoden anhand ihrer Semantik, darunter die Unterscheidung zwischen sicheren und idempotenten Methoden. Diese Begriffe helfen bei Wiederholungen und der Interpretation einer Absicht, verleihen aber keine Berechtigung. Ein GET kann sensible Informationen offenlegen. Ein PUT kann idempotent sein und trotzdem eine Produktiveinstellung überschreiben. Behandle Methodennamen als Hinweise für das Verhalten des Clients, nicht als Berechtigungsmodell.

Stelle dem Betreiber des Dienstes vor der Übergabe eines Tokens an einen Agenten diese Fragen:

  • Welche genauen Pfade und Methoden kann dieses Token aufrufen?
  • Prüft der Dienst den Zugriff für jede Ressource oder nur für die übergeordnete Sammlung?
  • Kann das Token Zugangsdaten erstellen, Berechtigungen ändern oder Exporte auslösen?
  • Kann eine Anfrage über eine Kennung in einen anderen Mandanten, ein anderes Projekt oder eine andere Umgebung gelangen?
  • Protokolliert der Dienst die Identität der Zugangsdaten und das Ergebnis der Anfrage?

Die unangenehme Frage lautet, ob eine Leseberechtigung mehr offenlegt, als die Aufgabe erfordert. Eine Repository-API kann einem Lesetoken Zugriff auf Quellcode, Kommentare zu Pull Requests, Build-Logs und Konfigurationen geben. Ein einziger schlecht gespeicherter Konfigurationswert kann Lesezugriff in Zugriff auf Geheimnisse verwandeln. Wenn der Agent nur den Zustand eines Deployments braucht, gib ihm einen Endpunkt, der genau diesen Zustand liefert. Übergib ihm kein allgemeines Repository-Token und nenne das Ergebnis geringstmögliche Berechtigung.

Das Anfrageschema ist ebenso wichtig wie der Berechtigungsumfang. Vergleiche diese beiden Anfragen:

POST /v1/releases/release-42/promote HTTP/1.1
Authorization: Bearer token-value
Content-Type: application/json

{"environment":"staging"}
POST /v1/admin/execute HTTP/1.1
Authorization: Bearer token-value
Content-Type: application/json

{"operation":"promote","arguments":{"environment":"staging"}}

Beide können ein Release weiterbefördern. Die erste lässt dem Server wenig Raum, den Vorgang zu interpretieren. Die zweite schafft einen administrativen Verteiler. Solche Verteiler ziehen Ausnahmen an, danach beliebige Operationsnamen und schließlich ein Token, dessen tatsächliche Rechte schwer zu beschreiben sind. Für Agenten vermeide ich sie, sofern der Server keine strenge Allowlist von Operationen verwendet und das Argumentenschema jeder Operation unabhängig prüft.

Verwende, wenn der Dienst das erlaubt, unterschiedliche Zugangsdaten für unterschiedliche Arten von Aktionen. Trenne Beobachtung von Änderungen und routinemäßige Änderungen von Änderungen an Identitäten oder Abrechnungen. Das verursacht zunächst mehr Einrichtungsaufwand, macht Autorisierungsfehler aber aussagekräftig. Eine Ablehnung zeigt, dass Aufgabendefinition und Zugangsdaten nicht zusammenpassen. Ein weitreichendes Token verwandelt jeden Fehler in eine erfolgreiche Anfrage, die du nachträglich untersuchen musst.

Lege kein langlebiges API-Geheimnis in eine Agentenaufforderung, eine Umgebungsdatei, eine Repository-Einstellung oder eine Tool-Konfiguration. Das Problem ist nicht nur die versehentliche Offenlegung in der Ausgabe. Agenten untersuchen ihre Umgebung, Werkzeuge sammeln Diagnosedaten, und ein Prozess mit Klartextzugriff kann das Geheimnis an ein anderes Ziel weitergeben. Halte das Geheimnis außerhalb des Agentenprozesses und autorisiere stattdessen die daraus entstehende Aktion.

SSH legt den Host offen, sofern du die Shell nicht bewusst entfernst

SSH hat standardmäßig einen großen Schadensumfang, weil ein interaktives Konto Dateien untersuchen, Programme ausführen, Konfigurationen ändern, Tunnel öffnen und jeden Netzwerkpfad nutzen kann, der diesem Konto offensteht. Die Absicht, nur einen Befehl auszuführen, beschränkt kein Konto, das eine normale Shell erhält.

RFC 4251 beschreibt SSH als Protokoll für sichere Remote-Anmeldungen und andere sichere Netzwerkdienste. Es unterstützt bewusst Sitzungen, Kanäle, Portweiterleitungen und mehrere Authentifizierungsmethoden. Für Administratoren sind diese Fähigkeiten nützlich. Für einen autonomen Akteur, der eine einzige begrenzte Wartungsaktion benötigt, sind sie ein schlechter Ausgangspunkt.

Auch der Befehl selbst ist wichtig. systemctl restart service-name wirkt begrenzt, bis du die umgebenden Rechte untersuchst: Welche Units darf das Konto neu starten? Können Unit-Dateien privilegierte Hooks ausführen? Kann das Konto diese Dateien bearbeiten? Und stammen Servicenamen aus validierten Eingaben? Ein scheinbar betrieblicher Befehl kann über den neu gestarteten Dienst auf Deployment-Zugangsdaten, eingebundene Volumes oder eine interne Steuerungsebene zugreifen.

Wenn SSH notwendig ist, entwickle ein kleines entferntes Programm mit geschlossener Eingabegrammatik. Das Programm sollte bekannte Anfragefelder bekannten Aktionen zuordnen. Es darf eine Anfrage nicht zu einem Shell-Befehl zusammensetzen. Akzeptiere keine Dateipfade, Hostnamen, regulären Ausdrücke, Shell-Fragmente oder Umgebungszuweisungen, sofern das Programm nicht jedes einzelne Element gegen eine enge Allowlist prüft.

Ein eingeschränkter Eintrag in authorized_keys kann diese Grenze sichtbar machen. Das folgende Muster erzwingt ein einziges Empfängerprogramm und entfernt mehrere SSH-Funktionen, die Agenten nur selten benötigen:

command="/usr/local/libexec/agent-maintenance",no-port-forwarding,no-agent-forwarding,no-X11-forwarding,no-pty ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIexample agent-runner

Diese Zeile löst die Autorisierung nicht allein. Das Programm agent-maintenance muss unbekannte Unterbefehle ablehnen und seine Argumente prüfen. Das Betriebskonto darf nur über die Datei-, Dienst- und Netzwerkrechte verfügen, die das Programm benötigt. Wenn das Programm sudo aufruft, muss die sudo-Regel ein festes ausführbares Programm nennen und darf keine Wege über Editoren, Interpreter, Wildcards oder Shell-Escapes erlauben.

Das Handbuch von OpenSSH zu authorized_keys dokumentiert command=, no-pty und Einschränkungen für Weiterleitungen. Behandle diese Optionen als Sicherheitsgurt, nicht als Fahrzeug. Sie entfernen mehrere einfache Auswege, aber ein erzwungener Befehl unter einem überprivilegierten Konto hat weiterhin überprivilegierten Zugriff.

Ein brauchbares Protokoll für entfernte Eingaben kann langweiliges JSON über die Standardeingabe sein:

{"action":"restart_worker","worker":"worker-17","request_id":"8b4f3c2a"}

Der Empfänger sollte nur restart_worker und Workernamen aus seinem eigenen Bestand akzeptieren. Vor der Ausführung sollte er ein Ereignis schreiben, ein festes Programm ohne Shell aufrufen, den Exit-Status erfassen und ein Abschlussereignis schreiben. Sendet der Agent worker-17; cat /etc/shadow, muss die Validierung den vollständigen Wert ablehnen, bevor irgendein Betriebssystembefehl ausgeführt wird.

Gib einem Agenten keinen SSH-Zugriff, nur weil ein Mensch dieselbe Arbeit bereits über SSH erledigt. Menschen erkennen eine ungewöhnliche Eingabeaufforderung, bemerken einen nicht passenden Hostnamen und brechen nach einem überraschenden Ergebnis ab. Bei Agenten muss die Einschränkung in der Schnittstelle verankert sein.

Protokolle müssen den Versuch und den resultierenden Zustand erklären

Eine Logzeile mit dem Inhalt «Anfrage fehlgeschlagen» ist kein Audit-Datensatz. Für das Debugging einer Clientbibliothek mag sie ausreichen, aber sie kann nicht klären, ob ein Agent etwas geändert hat, ob eine Person es genehmigt hat oder was nach einem Vorfall untersucht werden muss.

Erfasse für HTTP die Identität des Agentenlaufs, die Identität oder Bezeichnung der Zugangsdaten, den Zielhost, Methode, normalisierten Pfad, eine sichere Darstellung des Anfragetexts, den Antwortstatus, den Korrelationswert der Anfrage, Startzeit und Abschlussresultat. Entferne Geheimnisse und sensible Felder, bevor das Ereignis die Aktionsgrenze verlässt. Den Authorization-Header zum Beweiserhalt zu protokollieren, wäre eine selbst verursachte Sicherheitsverletzung.

Erfasse für SSH die Hostidentität, das entfernte Konto, den Namen des erzwungenen Befehls, validierte Argumente, die Identität des Quellprozesses, Exit-Status, Klassifizierung der Standardfehlerausgabe und die Kennung des entfernten Vorgangs. Ein roher Befehlsstring allein ist ein schwacher Nachweis, weil er Quoting-Verhalten verbergen kann und nicht zeigt, welche Argumente der Empfänger akzeptiert hat.

Die Ereignisfolge sollte Absicht und Wirkung unterscheiden. Diese Form funktioniert für beide Übertragungswege:

{"event":"authorization_granted","run":"r-204","action":"restart_worker","target":"worker-17"}
{"event":"action_started","run":"r-204","transport":"ssh","operation":"restart_worker","request_id":"8b4f3c2a"}
{"event":"action_finished","run":"r-204","outcome":"success","remote_status":0,"request_id":"8b4f3c2a"}

Wenn eine Verbindung nach action_started abbricht, schreibe outcome:"unknown" statt einen Fehler zu erfinden. Dieses Wort erzwingt den richtigen nächsten Schritt: Prüfe den entfernten Zustand, bevor du die Aktion wiederholst. Es macht auch eine spätere Untersuchung ehrlich.

Auch normale Logs haben ein Problem mit der Beweiskette. Ein Hostadministrator oder ein Prozess mit ausreichenden Rechten kann sie kürzen, ändern oder entfernen. Zentrale Sammlung hilft, kann aber weiterhin Lücken hinterlassen, wenn Sammler oder Netzwerkpfad ausfallen. Wenn das Protokoll Streitfragen zu Agentenaktionen klären muss, bewahre anhängende Datensätze mit Integritätsprüfungen auf und verifiziere sie außerhalb des Aktionspfads.

Eine Hashkette macht Änderungen erkennbar, indem jedes Ereignis den Digest des vorherigen Ereignisses einbezieht. Sie beweist nicht, dass der Aufzeichner jedes Ereignis gesehen hat, und macht eine unzuverlässige Uhr nicht vertrauenswürdig. Diese Grenzen sind wichtig. Die Kette beantwortet eine engere, aber nützliche Frage: Hat jemand diese aufbewahrte Folge nachträglich verändert?

Sallyport führt ein Sessions-Journal für Agentenläufe und ein Activity-Journal für einzelne Aufrufe. Beide werden aus einem verschlüsselten, hashverketteten Audit-Log abgeleitet. Der Befehl sp audit verify prüft diese Kette offline über dem Chiffretext. Das ist die richtige Eigenschaft, wenn du Belege untersuchen musst, ohne vorher Geheimnisse offenzulegen.

Timeouts erzeugen unbekannte Ergebnisse, keine fehlgeschlagenen Aktionen

Aktionen am Tresor stoppen
Sperre den Tresor, und Sallyport verweigert jede HTTP- und SSH-Aktion, bis er wieder entsperrt wird.

Netzwerkfehler führen dazu, dass ansonsten sorgfältige Teams doppelte Änderungen verursachen. Ein Client sendet eine Anfrage, die Gegenseite führt die Aktion aus und die Antwort geht verloren. Der Agent sieht ein Timeout und führt die Aktion erneut aus. Bei SSH kann dasselbe passieren, nachdem der entfernte Befehl gestartet wurde, aber bevor der Client seinen Exit-Status erhält.

Lass einen Agenten einen Transportfehler nicht als Erlaubnis interpretieren, eine Änderung zu wiederholen. Klassifiziere zuerst den Vorgang.

Ein Vorgang ist nur dann idempotent, wenn dieselbe Anfrage beim Wiederholen denselben beabsichtigten Zustand ohne zusätzliche Wirkung herstellt. Den gewünschten Zustand eines benannten Workers auf running zu setzen, kann diese Definition erfüllen. Eine Zahlung zu erstellen, einen Datensatz anzuhängen, ein Geheimnis zu rotieren oder einen Prozess neu zu starten, ist häufig nicht idempotent. Ein Neustart kann eine Wiederherstellungssequenz unterbrechen, die der erste Versuch bereits begonnen hat.

Verwende eine Idempotenzkennung, wenn die API das unterstützt. Der Dienst muss die Kennung zusammen mit der abgeschlossenen Wirkung speichern und bei einem Duplikat das frühere Ergebnis zurückgeben. Eine vom Client gelieferte Anfrage-ID, die der Server lediglich protokolliert, verhindert keine Duplikate.

Füge bei entfernten Befehlen eine Statusaktion hinzu, die eine präzise Frage beantworten kann. Nach einer fehlgeschlagenen Antwort auf restart_worker solltest du Generation, letzte Neustart-Anfrage-ID und Gesundheitszustand des Workers abfragen. Wenn der Empfänger die Anfrage-ID vor der Ausführung speichert und sie mit dem Status zurückgibt, kann er einem wiederholenden Agenten sagen, ob die Anfrage bereits ausgeführt wurde.

Diese Fehlerfolge zeigt, warum das wichtig ist:

  1. Der Agent fordert mit der Anfrage-ID 8b4f3c2a einen Neustart von worker-17 an.
  2. Der Empfänger speichert die ID und startet den Worker neu.
  3. Die SSH-Verbindung bricht ab, während der Worker stoppt.
  4. Der Agent fragt den Status ab, statt den Neustart erneut auszuführen.
  5. Die Statusantwort zeigt, dass dieselbe ID noch bearbeitet wird. Der Agent wartet und prüft den Gesundheitszustand.

Ein Wiederholungslimit löst unklare Ergebnisse nicht. Es begrenzt den Schaden, nachdem du die falsche Entscheidung zum Wiederholen getroffen hast. Die Beobachtung des Zustands behebt die Entscheidung selbst.

HTTP hat eine weitere Gefahr: Dienste geben manchmal einen Erfolgsstatus zurück, bevor die asynchrone Arbeit abgeschlossen ist. 202 Accepted bedeutet, dass der Server die Arbeit zur späteren Verarbeitung angenommen hat, nicht, dass der angeforderte Zustand bereits besteht. Verlange eine Operationsressource oder einen Statusendpunkt und lasse den Agenten auf das für die Aufgabe relevante Endergebnis warten.

Bei SSH gibt es eine entsprechende Falle, wenn ein Befehl Arbeit in den Hintergrund verschiebt und mit dem Status null endet. Behandle den Exit-Code eines Starters nicht als Beweis für eine abgeschlossene Wartungsaktion. Lass den Empfänger auf den Abschluss warten oder gib eine dauerhafte Operationskennung zurück, die der Agent abfragen kann.

Ein Shell-Befehl verbirgt mehr Rechte, als sein Text zeigt

Der kürzeste entfernte Befehl hat oft die umfassendsten versteckten Rechte. Shell-Erweiterung, geerbte Umgebung, aktuelles Verzeichnis, Konfigurationsdateien und Suchpfade für ausführbare Dateien beeinflussen gemeinsam, was ausgeführt wird. Ein Agent kann harmlos aussehenden Text erzeugen, der wegen der Interpretation durch den Host ein überraschendes Ergebnis auslöst.

Vermeide dieses Muster:

ssh ops@host "deploy $branch $environment"

Selbst wenn der Aufrufer Variablen heute korrekt quotet, interpretiert die entfernte Shell eine Befehlssprache. Das Deployment-Skript kann eigene Erweiterungen durchführen. Ein Branchname kann einen Quellort auswählen. Ein Umgebungsname kann Zugangsdaten oder einen Zielcluster bestimmen. Du musst jede Ebene untersuchen, bevor du behaupten kannst, dass die Eingabe begrenzt ist.

Verwende einen Empfänger, der strukturierte Eingaben liest und ein festes ausführbares Programm direkt aufruft. In den meisten Sprachen bedeutet das ein Argumentarray statt einer Zeichenkette, die an sh -c übergeben wird. Der Empfänger sollte die Zuordnung zwischen einem benutzerfreundlichen Zielnamen und einer hostspezifischen Kennung übernehmen. Lass den Agenten keine Dateipfade oder Servicenamen entdecken.

Dasselbe gilt für HTTP-Parameter. Ein Pfad wie /files?path=... kann strukturiert wirken, während der Server den Wert an eine Dateisystemoperation weitergibt. Eine API senkt das Risiko nur dann, wenn der Server die Bedeutung validiert, nicht wenn er die Befehlsanalyse hinter eine URL verschiebt.

Auch der Speicherort der Zugangsdaten verändert die Folgen eines kompromittierten Agentenprozesses. Speichert ein Agent einen privaten SSH-Schlüssel oder ein API-Token lokal, kann jeder Prozess mit Zugriff auf dieses Material später ohne den Agenten handeln. Eine getrennte Aktionsgrenze kann das Geheimnis verwahren und nur eine Anfrage plus Autorisierungsentscheidung an den entfernten Dienst weitergeben. Der Unterschied ist klar: Ein Geheimnis vor der Agentenausgabe zu verbergen, ist nicht dasselbe, wie es aus dem Agentenprozess herauszuhalten.

Sallyport verfolgt diesen zweiten Ansatz für HTTP-Zugangsdaten und SSH-Schlüssel: Die App verwahrt sie in einem verschlüsselten Tresor und führt die angeforderte Aktion aus, statt das Schlüsselmaterial an den Agenten weiterzugeben. Das macht eine gefährliche Anfrage nicht sicher. Ziele müssen weiterhin begrenzt und Genehmigungen geprüft werden.

Wähle den Transport anhand eines schriftlichen Fähigkeitsvergleichs

Eine Richtliniensprache vermeiden
Verwende eine feste Entscheidungskette: Tresorsperre, Laufgenehmigung und optional eine Genehmigung für jede Nutzung sensibler Schlüssel.

Du kannst eine begründete Entscheidung ohne einen langen Risiko-Workshop treffen. Schreibe eine Zeile für den geplanten HTTP-Aufruf und eine für den geplanten SSH-Befehl und fülle beide mit denselben Fakten. Vage Bezeichnungen wie «Lesezugriff» oder «Wartungszugriff» zählen nicht.

Verwende diesen Vergleich in fünf Punkten:

  1. Beschreibe das genaue Ergebnis, zum Beispiel «Deployment-Zustand für Dienst A abrufen» oder «worker-17 nach einer fehlgeschlagenen Gesundheitsprüfung neu starten».
  2. Nenne jedes erreichbare Ziel: API-Sammlungen, Projekte, Hosts, Dienste, Dateien und Netzwerkziele.
  3. Liste Änderungen auf, die dieselben Zugangsdaten oder dasselbe Konto zusätzlich zum beabsichtigten Ergebnis ausführen können.
  4. Beschreibe, welche Belege nach einem Timeout, einer Ablehnung oder einem scheinbaren Erfolg verfügbar sind.
  5. Definiere die Genehmigungsgrenze: ein Lauf, ein Aufruf oder eine vorab genehmigte Routine mit fester Identität.

Wähle HTTP, wenn die API-Zeile eine kleinere Zielmenge, eine engere Aktion und einen klareren Datensatz beschreibt. Wähle SSH, wenn der entfernte Empfänger diese Eigenschaften besser erfüllt als die API oder wenn es für die benötigte Hostaktion keine API gibt. Wenn keine der beiden Zeilen ausreichend eng ist, verbinde den Agenten noch nicht. Baue zuerst den fehlenden Endpunkt oder Empfänger.

Dieser Vergleich erkennt auch eine verbreitete schlechte Empfehlung: «Verwende SSH für Lesezugriffe und APIs für Schreibzugriffe.» Sie klingt vernünftig, weil Shell-Zugriff betrieblich und API-Aufrufe transaktional wirken. Sie scheitert daran, dass das Lesen eines Hosts Zugangsdaten, Quellcode, Kundendaten und Netzwerktopologie offenlegen kann, während eine sorgfältig begrenzte API-Änderung genau einen gewünschten Zustand ändern kann. Lesen und Schreiben sind keine ausreichenden Risikokategorien. Entscheidend sind erreichbare Daten und erreichbare Nebenwirkungen.

Ein Team, dessen Agent Build-Fehler diagnostiziert, braucht möglicherweise einen HTTP-Endpunkt für den Jobstatus, einen API-Aufruf für ein begrenztes Logfenster und nur dann einen Empfänger auf einem einzelnen Host, wenn eine bestimmte Reparatur das erfordert. Die Aufteilung schafft zwar zusätzliche Schnittstellen. Sie verhindert aber auch, dass eine routinemäßige Diagnoseaufgabe ein dauerhaftes Shell-Zugangsmittel mitführt, nur weil eine seltene Reparatur es benötigt.

Die Genehmigung sollte sich nach den Kosten einer falschen Aktion richten

Einen fehlerhaften Lauf stoppen
Widerrufe einen unerwarteten Agentenlauf sofort im Sessions-Journal, statt dauerhaften Zugriff bestehen zu lassen.

Eine Genehmigung ist am nützlichsten an einer Grenze, die eine Person verstehen kann. Wer für jede harmlose Statusabfrage bestätigen muss, lernt, ohne zu lesen zu klicken. Eine einzige weitreichende Genehmigung für jedes künftige ausführbare Programm macht die Prüfung vollständig bedeutungslos.

Verwende eine Genehmigung pro Lauf, wenn ein neuer Agentenprozess zum ersten Mal handeln möchte und seine Identität klar angezeigt werden kann. Die Person kann das anfragende Programm mit der erwarteten Aufgabe vergleichen. Widerrufe den Lauf bei unerwartetem Verhalten und untersuche seine bisherigen Aufrufe anhand des Aktionsdatensatzes.

Verwende eine Genehmigung pro Aufruf für Aktionen mit irreversiblen oder teuren Nebenwirkungen: Rotation von Zugangsdaten, Löschung, Promotion in die Produktion, Kontoänderungen und alles, dessen Ziel der Agent dynamisch auswählen kann. Die Genehmigungsaufforderung sollte Ziel und Vorgang in gewöhnlichen Begriffen nennen. «Tool-Anfrage ausführen» sagt der prüfenden Person fast nichts.

Versuche nicht, dieses Urteil durch eine ausufernde Regelsprache für jede Ausnahme zu ersetzen. Teams pflegen dann eine zweite Programmierumgebung, deren Sonderfälle am Ende genau das erlauben, was sie blockieren wollten. Eine kleine Gruppe fester Kontrollen ist leichter zu prüfen: der Sperrstatus des Tresors, eine Laufgenehmigung und optional die Genehmigung jeder Nutzung eines sensiblen Schlüssels.

Eine Genehmigung kompensiert keine Zugangsdaten mit unbegrenzten Rechten. Sie gibt einer Person die Möglichkeit, eine Aktion zu stoppen, bevor sie den Rechner verlässt. Der zugrunde liegende Dienst muss seine Autorisierung weiterhin selbst durchsetzen, und der Audit-Datensatz muss festhalten, was nach der Genehmigung passiert ist.

Baue die Grenze für entfernte Aktionen vor dem ersten Vorfall

Die beste erste Änderung ist meist keine kompliziertere Agentenaufforderung. Ersetze ein weitreichendes Geheimnis durch eine Aktionsgrenze mit klarer Eingabegrammatik, begrenzter Zielmenge, einem Timeout-Plan und Belegen, die ein anderer Betreiber prüfen kann.

Bitte den Betreiber des Dienstes bei einer HTTP-Aufgabe um einen Endpunkt und Zugangsdaten, deren Berechtigungen genau zur einen Aktion passen. Teste abgelehnte Pfade und Methoden ebenso bewusst wie erfolgreiche Aufrufe. Erstelle bei einer SSH-Aufgabe ein eigenes Konto, deaktiviere interaktive Funktionen, erzwinge ein Empfängerprogramm und teste fehlerhafte Eingaben dagegen. Führe die Tests über dieselbe Route aus, die der Agent verwenden wird, weil sich Netzwerkzugriff und Identitätsprüfungen oft von denen auf dem Laptop eines Administrators unterscheiden.

Simuliere anschließend den Fehler, den niemand gern testet: Schließe die entfernte Arbeit ab und trenne die Verbindung, bevor die Antwort den Aufrufer erreicht. Wenn dein Agent anhand des gespeicherten Datensatzes und des entfernten Zustands nicht entscheiden kann, ob er warten, abfragen oder wiederholen soll, wird das Design unter Druck doppelte Arbeit verursachen.

Die Wahl des Protokolls wird einfach, sobald du auf diesen Eigenschaften bestehst. Verwende die Schnittstelle, die die kleinste benennbare Fähigkeit gewährt, nach einem Fehler eine verlässliche Antwort liefert und eine nachvollziehbare Aufzeichnung der Aktion hinterlässt, die nicht vom Gedächtnis einer Person an eine Terminalsitzung abhängt.

FAQ

Wann sollte ein KI-Agent HTTP statt SSH verwenden?

Verwende HTTP, wenn sich die Aufgabe auf eine eng begrenzte Ressourcenaktion abbilden lässt, die der Dienst selbst authentifizieren, autorisieren, validieren und protokollieren kann. SSH passt, wenn die Aufgabe tatsächlich Untersuchungen auf dem Host oder ein entferntes Programm erfordert, für das es keine geeignete API gibt.

Ist SSH für einen KI-Agenten immer zu gefährlich?

SSH muss nicht automatisch vollständigen Shell-Zugriff bedeuten. Das ist aber häufig das Ergebnis, weil Teams die Einrichtung eines Administratorschlüssels kopieren. Beschränke das Konto, erzwinge genau einen Befehl, deaktiviere Weiterleitungen und lasse den Befehl seine Argumente vor der Ausführung prüfen.

Beseitigen eingeschränkte API-Tokens den möglichen Schadensumfang?

API-Berechtigungsbereiche begrenzen Aktionen nur dann, wenn die API sie für die erreichbaren Endpunkte und Methoden tatsächlich durchsetzt. Lese-, Änderungs-, Token-Erstellungs- und Exportfunktionen können unterschiedlichen Berechtigungen unterliegen. Teste daher jede davon, statt einem Namen für den Berechtigungsbereich zu vertrauen.

Was sollten Protokolle über Agentenaktionen erfassen?

Ein brauchbarer Datensatz nennt den Agentenprozess, die Identität der Zugangsdaten, das Ziel, die Anfrage oder den Befehl, das Autorisierungsergebnis und den Ausgang. Bei Änderungen solltest du außerdem die Ressourcenkennung und eine Anfrage-ID aufbewahren, damit sich die Änderung nachvollziehen lässt.

Kann ein Agent eine abgelaufene entfernte Aktion sicher wiederholen?

Ein Timeout beweist nur, dass der Client keine Antwort erhalten hat. Die Gegenseite kann die Aktion abgeschlossen haben, noch daran arbeiten oder sie nach dem Verbindungsabbruch abgelehnt haben. Wiederhole sie erst, nachdem du die Idempotenz geprüft und den erwarteten Zustand abgefragt hast.

Wie messe ich den möglichen Schadensumfang eines SSH-Befehls?

Behandle einen Befehl als Fähigkeit mit eigener Eingabegrammatik, eigenem Betriebskonto, Arbeitsverzeichnis und erreichbarem Netzwerk. Ein Befehl, der beliebige Pfade, Shell-Fragmente oder Umgebungsvariablen akzeptiert, verleiht deutlich mehr Rechte, als sein kurzer Name vermuten lässt.

Soll ich jeden API-Aufruf eines Agenten genehmigen?

Die Genehmigung sollte einen identifizierbaren ausführbaren Prozess abdecken und mit dessen Ende ablaufen. Eine pauschale Genehmigung für alle künftigen Prozesse beseitigt genau die Grenze, an der eine Person einen neuen oder ausgetauschten Agenten erkennen könnte.

Sind schreibgeschützte API-Berechtigungen für Agenten sicher?

In der Regel nein. Lesezugriff kann Quellcode, Kundendaten, Konfigurationen oder Zugangsdaten offenlegen, die an einer ungeeigneten Stelle gespeichert sind. Gewähre nur den kleinsten Sammlung- oder Endpunktbereich, der die Aufgabe beantwortet, und trenne Suchzugriff vom Exportzugriff.

Wann ist SSH die bessere Wahl für Automatisierung?

Verwende SSH, wenn die API die nötige Aktion nicht anbietet, wenn du lokale Hostinformationen brauchst oder wenn ein kontrolliertes Wartungsprogramm bereits die sicherste Schnittstelle bereitstellt. Wähle SSH nicht nur, weil sich ein Shell-Befehl schneller schreiben lässt als ein API-Client.

Worin unterscheidet sich ein manipulationsnachweisbares Audit-Protokoll von normalen Logs?

Ein Audit-Trail muss stille Änderungen erschweren und klar ausweisen, wer eine Aktion autorisiert und ausgeführt hat. Normale Anwendungsprotokolle helfen beim Debugging, aber Administratoren oder kompromittierte Prozesse können sie oft ändern oder löschen, ohne Spuren zu hinterlassen.

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