02 / Blog · 19.08.2026
Eine Forced-Command-SSH-Grenze für einen Codex-Worker
Warum der Homepage-Worker Codex nur über aidev auf dem AI-CLI-Server erreicht und aus einem SSH-Zugang keinen allgemeinen Fernzugriff macht.
Das Konto ist Teil der Architektur
Ein entfernter KI-Worker braucht Rechenumgebung und eine gültige Codex-Sitzung. Die einfache Lösung wäre, Authentifizierung in den Web-Container zu kopieren oder einen normalen SSH-Zugang zu verwenden. Beides vergrößert die Grenze unnötig. Ein Web-Container sollte weder ein Codex-Home besitzen noch auf einem anderen Server beliebige Befehle ausführen können.
Die Homepage verwendet deshalb einen festen Zielpunkt:
aidev@5.45.99.175 auf dem AI-CLI-Server. Das ist keine austauschbare
Konfigurationsbequemlichkeit, sondern ein geprüfter Vertrag. Der Client lehnt
andere Ziele ab, verwendet strikte Host-Key-Prüfung und deaktiviert Forwarding.
Staging und Produktion besitzen getrennte Schlüssel, aber beide landen am
gleichen eng begrenzten Protokoll.
Diese Trennung verhindert auch einen subtilen Betriebsfehler: Eine gültige
Sitzung des Web- oder GUI-Benutzers ist nicht automatisch die richtige
Laufzeitidentität. Codex läuft dort, wo aidev bereits kontrolliert
authentifiziert ist. Weder die Authentifizierungsdatei noch Sitzungsverlauf oder
ein komplettes Codex-Home werden in Anwendung, Image oder Webserver kopiert.
SSH ohne frei wählbaren Befehl
Ein SSH-Schlüssel gewährt normalerweise mehr, als dieser Job benötigt. Die
zugehörigen Einträge in authorized_keys erzwingen daher genau einen Wrapper.
Der vom Client gesendete Originalbefehl wird nicht mit einer Shell ausgewertet.
Der Wrapper zerlegt nur ein winziges Protokoll aus Modus, erlaubter Websuche und
Zeitlimit. Falsche Anzahl, unbekannter Modus oder zu großes Limit führen zum
Abbruch.
Auch nach dieser Prüfung bleibt der Lauf eingeschränkt. Strukturierte Arbeit läuft in einer read-only Sandbox. Bildarbeit erhält ein eigenes temporäres Verzeichnis. Shell, Browser, Plugins, Apps, Multi-Agent-Funktionen und weitere nicht benötigte Werkzeuge sind deaktiviert. Eine globale Sperre verhindert parallele Läufe, Request und Antwort besitzen Größenlimits, und ein Timeout beendet festgefahrene Prozesse.
Damit wird aus SSH kein allgemeiner Fernzugriff. Der Anwendungsschlüssel kann weder eine interaktive Shell öffnen noch einen anderen Befehl wählen. Er kann einen begrenzten Auftrag an genau den vorgesehenen Runner übergeben.
Das Ergebnis überquert dieselbe schmale Grenze
Die Grenze gilt in beide Richtungen. Strukturierte Ergebnisse müssen das mitgesendete strikte JSON-Schema erfüllen. Bei einem Bild akzeptiert der Wrapper nur eine Datei aus dem temporären Arbeitsbereich oder dem vorgesehenen Ausgabeverzeichnis, nur unterstützte Bitmap-Typen und nur bis zum festgelegten Limit. Pfadauflösung verhindert, dass eine angegebene Datei aus einem anderen Verzeichnis gelesen wird. Anschließend validiert die Homepage das Ergebnis erneut, bevor TYPO3 etwas speichert.
Fehler werden bewusst grob nach außen gemeldet. Eine ungültige Anmeldung, Rate-Limitierung oder Zeitüberschreitung ist betrieblich relevant. Der Inhalt interner Fehlerlogs oder Authentifizierungsdaten ist es für den aufrufenden Container nicht.
Provisionierung ist nicht Deployment
Die AI-Grenze wird von einem eigenen Ansible-Playbook provisioniert. Es prüft
den aidev-Account, dessen Codex-Anmeldung, den privaten Runtime-Ordner, den
Wrapper und die erlaubten öffentlichen Schlüssel. Normale Staging- und
Produktionsdeployments verändern den AI-CLI-Server nicht. Sie liefern nur den
passenden privaten Schlüssel als Docker Secret aus und führen einen echten
Schema-Probeauftrag aus.
Das hält Verantwortlichkeiten klein: Die Provisionierung verwaltet den Vertrauenspunkt. Das Deployment beweist, dass seine eigene Identität diesen Punkt erreicht. Der Worker führt nur das definierte Protokoll aus. Keine dieser Schichten muss so mächtig sein wie alle drei zusammen.