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.

Ein strukturierter Auftrag passiert einen schmalen gesperrten SSH-Kanal, während Shell und fremde Dateien blockiert bleiben.

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.