# Kann SSH-Umgebungsweitergabe lokalen Kontext preisgeben?

SSH-Umgebungsweitergabe kann weit mehr lokalen Kontext preisgeben, als ein entfernter Auftrag benötigt. Der Kanal ist verschlüsselt, doch die Verschlüsselung schützt nur den Transport. Sie macht `AWS_PROFILE`, `GIT_AUTHOR_EMAIL`, einen Mandantennamen oder einen internen Schalter nicht zu geeigneten Eingaben für einen Prozess auf einem anderen Rechner.

Ich behandle jede weitergegebene Variable wie ein Argument des entfernten Befehls. Sie braucht daher einen Namen, einen Grund, einen Verantwortlichen und einen Test. Ein Platzhalter aus einer bequemen Laptop-Konfiguration erfüllt diesen Maßstab nicht, weil sich seine Bedeutung mit jeder neuen passenden lokalen Variable ändert.

Das sichere Ziel ist keine leere entfernte Umgebung. `sshd`, das Anmeldekonto, die Shell und vorgeschaltete Programme erzeugen eine eigene Basis. Das Ziel ist enger: Der Client trägt genau die schriftlich vereinbarten Arbeitsvariablen bei, der Server akzeptiert keine größere Menge und ein Test belegt sowohl die notwendigen Werte als auch die abgewiesenen Köder.

## Die Weitergabe braucht die Zustimmung beider SSH-Seiten

Die Umgebungsweitergabe von OpenSSH hat zwei Schranken. Auf dem Client wählt `SendEnv` Namen aus der Umgebung des lokalen Prozesses, während clientseitiges `SetEnv` feste Paare in der Form `NAME=WERT` liefert. Auf dem Server entscheidet `AcceptEnv`, welche gesendeten Namen in die Sitzung gelangen. Normalerweise wird ein Name nur übernommen, wenn der Client ihn anbietet und der Server ihn akzeptiert.

RFC 4254 beschreibt den Mechanismus darunter. Vor dem Start der Shell oder des Befehls kann der Client eine SSH-Kanalanfrage vom Typ `env` mit einem Variablennamen und einem Wert senden. Der RFC warnt vor unkontrollierten Umgebungseinstellungen in privilegierten Prozessen und empfiehlt eine Zulassungsliste oder das Setzen nach dem Entzug ausreichender Rechte. Diese Warnung gehört zur Protokollspezifikation selbst.

Die OpenSSH-Handbücher nennen eine Ausnahme, die Prüfungen oft verwirrt: Fordert der Client ein Pseudoterminal an, wird `TERM` immer gesendet und akzeptiert, weil das Protokoll sie benötigt. Führen Sie Automatisierung ohne Terminal mit `ssh -T` aus. Damit verschwinden `TERM`, interaktives Verhalten und Überraschungen aus Startdateien aus diesem Pfad.

Aus diesem Zusammenspiel folgen vier Aussagen.

- Ein breites `SendEnv` bleibt bei einem Server ohne Annahmeregel wirkungslos, wird aber mit einer späteren Erweiterung von `AcceptEnv` aktiv.
- Ein breites `AcceptEnv` bleibt bei einem vorsichtigen Client wirkungslos, doch ein berechtigter Nutzer kann eine andere Client-Konfiguration verwenden.
- Keine Seite kann den ganzen Vertrag allein durchsetzen, wenn verschiedene Personen die Konfigurationen verwalten.
- Ein erfolgreicher Befehl sagt nichts darüber aus, welche Umgebungsanfragen der Server verworfen hat.

OpenSSH kann eine angebotene Variable ignorieren und die Sitzung fortsetzen. Definiert die entfernte Shell denselben Namen bereits, kann ein Test des Endwerts der Weitergabe einen Wert zuschreiben, der nie übertragen wurde.

## Platzhalter machen zukünftigen lokalen Zustand zur entfernten Eingabe

`SendEnv WORKFLOW_*` bedeutet nicht „die heute geprüften Variablen“. Es umfasst alle passenden Namen in der Umgebung jedes zukünftigen SSH-Prozesses. Wochen später kann jemand `WORKFLOW_DEBUG_DUMP`, `WORKFLOW_CUSTOMER` oder `WORKFLOW_TOKEN_FILE` in sein Profil aufnehmen, und die alte Regel erhält unbemerkt neues Verhalten.

Die Weitergabe von Gebietsschemata zeigt das Problem gut. Viele Arbeitsplatzkonfigurationen senden `LANG` und `LC_*`, damit interaktive Sitzungen Text richtig darstellen. Für menschliche Anmeldungen kann das passen, doch ein nicht interaktives Build- oder Bereitstellungskonto braucht diese Werte nicht automatisch. Sie ändern Sortierung, Zeichenklassen, Datumsdarstellung und Diagnosemeldungen. Ein Auftrag, der Ausgaben auswertet, kann ohne jedes Geheimnis scheitern.

Besonders riskant sind praktisch wirkende Namensräume:

- `AWS_*` kann Profile, Regionen, Werte mit Bezug zu Zugangsdaten und Konfigurationspfade umfassen.
- `GIT_*` kann Identität, Ablaufverfolgung, alternative Objektverzeichnisse oder askpass-Verhalten transportieren.
- `CI_*` mischt oft harmlose Build-Kennungen mit Anbieterinformationen und temporären Pfaden.
- `LC_*` wirkt kosmetisch, bis ein Skript von stabiler Sortierung oder stabilen Meldungen abhängt.
- `APP_*` wächst mit der Anwendung und hat selten eine einheitliche Sicherheitsbedeutung.

Bewerten Sie einzelne Namen statt des gesamten Namensraums. `DEPLOY_REGION` kann nötig sein, während `AWS_PROFILE` nur den Arbeitsplatz beschreibt. `BUILD_REF` kann nötig sein, während `GIT_CONFIG_COUNT` die laufende Git-Konfiguration ändert. Ein gemeinsames Präfix ordnet Namen, bildet aber keine Vertrauensgrenze.

Auch Werte ohne Zugangsdaten geben Kontext preis. Ein Pfad zeigt Nutzernamen und Repository-Struktur, ein Profil bezeichnet Konto oder Umgebung, und ein Ablaufverfolgungsschalter kann Befehlsdaten in ein gemeinsames Protokoll schreiben. Ein Agent kann diesen Kontext später verwenden. Ein Leck betrifft unbeabsichtigte Offenlegung und Einflussnahme, nicht nur geheime Zeichenketten.

## Eine harmlose Ausnahme kann sich Monate später ausweiten

Meist erzeugt Konfigurationsdrift das Leck, nicht eine einzelne offensichtlich riskante Änderung. Zuerst fügt ein Entwickler `SendEnv APP_*` hinzu, weil ein Test `APP_COLOR=0` braucht. Der Server lehnt es ab. Später ergänzt ein Administrator `AcceptEnv APP_*` für ein anderes Team auf demselben gemeinsam genutzten Rechner. Jede Prüfung sieht nur eine Hälfte der Vereinbarung.

Die nächste Verbindung verknüpft die schlafenden Regeln. In der lokalen Shell stehen nun `APP_CUSTOMER=acme-lab`, `APP_TRACE=1` und `APP_CONFIG=/Users/lee/work/private/config`. Der Client bietet alle Werte an, der Daemon nimmt sie an und ein Diagnoseprogramm führt nach einem Fehler `env` aus. Lokale Identität, Kundenkontext, Pfad und Ablaufverfolgung landen ohne Freigabe in einem gruppenlesbaren Protokoll.

Das Entfernen des Server-Platzhalters schützt künftige Sitzungen, löscht aber nicht das alte Protokoll. Behandeln Sie den Fund als kleinen Vorfall:

1. Stoppen Sie die breite Annahme und prüfen Sie die Daemon-Konfiguration.
2. Ermitteln Sie Konten, Clients und Zeitraum, in dem beide Muster zusammenwirkten.
3. Suchen Sie in freigegebenen Protokollen nach den Namen, nicht nach empfindlichen Werten.
4. Klären Sie, ob ein Wert Verhalten änderte oder Kontext an andere Nutzer verriet.
5. Ersetzen Sie den Platzhalter durch genaue Namen und ergänzen Sie Köder.

„Der Server lehnt das derzeit ab“ rechtfertigt deshalb keine breite Client-Regel. Schlafende Konfiguration hat beim Erwachen oft keinen Verantwortlichen. Entfernen Sie unnötige Angebote auch vor einem strengen Server und unnötige Annahmen auch bei vorsichtigen Clients.

Auch die umgekehrte Drift kommt vor. Ein Server akzeptiert lange `LC_*` für interaktive Nutzer, dann beginnt ein neues Automatisierungsabbild mit dem Senden. Die Bereitstellung erbt das `LC_COLLATE` eines Entwicklers und erzeugt eine andere Dateireihenfolge. Das ist vielleicht keine Offenlegung, aber eine Integritätsstörung durch denselben Mechanismus. Prüfen Sie Vertraulichkeit und Verhalten gemeinsam.

## Prüfen Sie die tatsächlich verwendete SSH-Konfiguration

Lesen Sie vor einer Änderung die ausgewertete Client-Konfiguration. `ssh -G` verarbeitet `Host`, `Match`, Einbindungen sowie Nutzer- und Systemdateien und gibt das Ergebnis für das Ziel aus. Eine vermeintlich maßgebliche Datei kann gegen einen früheren Wert verlieren oder zusätzliche Regeln aus einer Einbindung erhalten.

Führen Sie dies mit demselben Konto und Startkontext wie der Arbeitsablauf aus:

```sh
ssh -G deploy-prod |
  awk '$1 == "sendenv" || $1 == "setenv" { print }'
```

Ein typisches unsicheres Ergebnis sieht so aus:

```text
sendenv LANG
sendenv LC_*
sendenv AWS_*
setenv WORKFLOW_KIND=deploy
```

`ssh -G` zeigt die wirksamen Regeln, nicht die aktuellen Werte. Damit landen keine Zugangsdaten in der Prüfausgabe. Die Namen und Muster müssen dennoch mit der Umgebung des Prozesses verglichen werden, der SSH wirklich startet.

Erfassen Sie nur die Namen:

```sh
env | sed 's/=.*//' | LC_ALL=C sort > local-env.names
grep -E '^(LANG|LC_|AWS_|WORKFLOW_)' local-env.names
```

Der reguläre Ausdruck ist ein Prüfwerkzeug, keine wiederverwendbare Richtlinie. Passen Sie ihn an alle Muster an. Starten Supervisor, IDE, Agent oder Zeitplaner SSH, prüfen Sie deren Umgebung statt Ihrer interaktiven Shell. Vererbung folgt dem Prozessbaum.

Prüfen Sie den Server getrennt. `sshd -T` validiert und druckt wirksame Einstellungen; bei `Match`-Blöcken müssen die Verbindungsmerkmale angegeben werden:

```sh
sudo sshd -T \
  -C user=deploybot,host=deploy.example,addr=192.0.2.44 |
  grep '^acceptenv'
```

Setzen Sie echten Nutzer, Rechner und echte Adresse ein. Die Dokumentationsadresse gehört nur ins Beispiel. Führen Sie vor dem Neuladen außerdem `sudo sshd -t` aus. Eine Härtung darf den Fernzugriff nicht unterbrechen.

## Eine eigene Client-Datei macht die Zulassung verständlich

Für Automatisierung ist eine kleine, mit `-F` angegebene SSH-Datei am verlässlichsten. Laut Handbuch ersetzt sie die normale Nutzerdatei und sorgt dafür, dass die systemweite Client-Datei ignoriert wird. Ein späteres Arbeitsplatz-Update kann dem Ablauf so keine Locale-Platzhalter hinzufügen.

```sshconfig
Host deploy-prod
    HostName deploy.example
    User deploybot
    IdentityFile ~/.ssh/deploy_ed25519
    IdentitiesOnly yes
    RequestTTY no
    SendEnv DEPLOY_REGION
    SendEnv BUILD_REF
    SetEnv WORKFLOW_KIND=deploy
```

Geben Sie die Datei ausdrücklich an:

```sh
ssh -F ./deploy-ssh.conf deploy-prod /usr/local/bin/release
```

`SendEnv` liest den Wert aus der Umgebung des lokalen `ssh`-Prozesses und passt zu Eingaben, die sich pro Lauf ändern. Clientseitiges `SetEnv` trägt einen festen Wert in die Konfiguration ein. Verwenden Sie es für eine konstante, nicht geheime Kennung, nicht für Zugangsdaten oder häufig wechselnde Werte.

OpenSSH kann mit einem `-` vor einem `SendEnv`-Muster zuvor ausgewählte Namen entfernen:

```sshconfig
Host deploy-prod
    SendEnv -*
    SendEnv DEPLOY_REGION BUILD_REF
```

Die Bereinigung betrifft nur bis dahin gesammelte Namen. Eine spätere Einbindung kann sie erneut hinzufügen. Deshalb bildet Subtraktion keine dauerhafte Grenze. Eine eigene Datei mit `-F` hat weniger bewegliche Teile und passt auf einen Bildschirm.

Zugangsdaten gehören nicht in diesen Vertrag. Ein weitergegebenes Token wird normaler Zustand des entfernten Prozesses und kann Kindprozesse, Ablaufverfolgung, Absturzberichte, `/proc` oder eine versehentliche `env`-Ausgabe erreichen. SSH schützt den Transport, nicht den Lebenszyklus nach der Zustellung.

## Der Server sollte genaue Namen für ein begrenztes Konto annehmen

Der Server ist die letzte Ablehnungsstelle vor dem Sitzungsstart. OpenSSH nimmt standardmäßig keine Variablen an, abgesehen vom Sonderfall `TERM` mit Pseudoterminal. Behalten Sie diesen globalen Standard und ergänzen Sie genaue Namen nur für das Arbeitskonto.

```sshdconfig
Match User deploybot
    AcceptEnv DEPLOY_REGION
    AcceptEnv BUILD_REF
    AcceptEnv WORKFLOW_KIND
```

Verwenden Sie weder `AcceptEnv APP_*` noch `AcceptEnv AWS_*` oder einen nackten Platzhalter. Das `sshd_config`-Handbuch warnt ausdrücklich, dass manche Variablen eingeschränkte Nutzerumgebungen umgehen können. Ein Platzhalter genehmigt außerdem künftige Namen ohne weitere Serveränderung.

Ein breites globales `AcceptEnv` schwächt alle Konten. Ein engerer `Match User`-Block entfernt bereits global angenommene Namen nicht; Einträge können sich sammeln. Brauchen interaktive Nutzer Locale-Werte, beschränken Sie die Ausnahme auf deren Gruppe und prüfen Sie jeden Fall mit `sshd -T -C`.

Serverseitiges `SetEnv` ist eine getrennte Steuerung. Es setzt Konstanten in Kindersitzungen und überschreibt Standardwerte sowie Werte aus `AcceptEnv` oder `PermitUserEnvironment`. Gehört eine Konstante dem Server, setzen Sie sie dort statt sie vom Client anzunehmen.

`PermitUserEnvironment` steuert `~/.ssh/environment` und `environment=` in authorized_keys. OpenSSH schaltet es standardmäßig ab. Eine Prüfung nur von `AcceptEnv` kann diese Quelle übersehen. Lassen Sie sie ohne klaren Bedarf aus und nehmen Sie ihre Muster sonst in denselben Vertrag auf.

Eine genaue Namensliste prüft keine Werte. Ein erlaubtes `DEPLOY_REGION` kann Leerraum, Shell-Metazeichen, einen Zeilenumbruch oder eine verbotene Region enthalten. SSH transportiert Daten, doch `eval`, eine Expansion ohne Anführungszeichen oder eine erzeugte Konfiguration kann daraus Syntax machen.

Validieren Sie jeden Wert am entfernten Einstiegspunkt:

```sh
case ${DEPLOY_REGION-} in
    us-east-1|us-west-2) ;;
    *)
        printf 'invalid DEPLOY_REGION\n' >&2
        exit 64
        ;;
esac

case ${BUILD_REF-} in
    [0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]*)
        ;;
    *)
        printf 'invalid BUILD_REF\n' >&2
        exit 64
        ;;
esac
```

Die Prüfung muss zum wirklichen Vertrag passen. Das kurze Muster zeigt nur eine Formprüfung. Verlangt eine Veröffentlichung eine vollständige Kennung, prüfen Sie genaue Länge und Vorkommen im Repository. Eine Prüfung, die nur leere Zeichenketten abweist, reicht nicht.

Prüfen Sie nach der Änderung das wirksame Ergebnis:

```sh
sudo sshd -t
sudo sshd -T \
  -C user=deploybot,host=deploy.example,addr=192.0.2.44 |
  grep -E '^(acceptenv|permituserenvironment|setenv)'
```

Speichern Sie die Ausgabe mit der Konfigurationsprüfung. Sie zeigt, was der Daemon für die konkrete Verbindung ausgewertet hat, und ist aussagekräftiger als ein Bild eines einzelnen Fragments.

## Belegen Sie erforderliche Werte und abgewiesene Köder entfernt

Ein brauchbarer Test prüft positive und negative Fälle im entfernten Prozess. Setzen Sie eindeutige Marker für Pflichtwerte, Köder für frühere Platzhalter, starten Sie eine nicht interaktive Sitzung mit der eigenen Datei und lassen Sie die Shell bei einem Vertragsbruch fehlschlagen.

Diese Abfolge erwartet vom Client nur `DEPLOY_REGION`, `BUILD_REF` und das feste `WORKFLOW_KIND`:

```sh
export DEPLOY_REGION='env-audit-region'
export BUILD_REF='env-audit-ref'
export AWS_PROFILE='must-not-cross'
export LC_AUDIT_CANARY='must-not-cross'
export APP_PRIVATE_PATH='must-not-cross'

ssh -F ./deploy-ssh.conf -T deploy-prod 'sh -s' <<'REMOTE'
set -eu

test "$(printenv DEPLOY_REGION)" = 'env-audit-region'
test "$(printenv BUILD_REF)" = 'env-audit-ref'
test "$(printenv WORKFLOW_KIND)" = 'deploy'

for name in AWS_PROFILE LC_AUDIT_CANARY APP_PRIVATE_PATH; do
    if printenv "$name" >/dev/null 2>&1; then
        printf 'unexpected forwarded variable: %s\n' "$name" >&2
        exit 1
    fi
done

printf '%s\n' 'SSH environment contract passed'
REMOTE
```

Die erwartete Ausgabe ist eine Zeile:

```text
SSH environment contract passed
```

Entfernen Sie danach einen lokalen Pflichtwert. `SendEnv` kann einen fehlenden Namen nicht senden, daher muss die entfernte Prüfung scheitern:

```sh
unset BUILD_REF
if ssh -F ./deploy-ssh.conf -T deploy-prod 'test -n "$BUILD_REF"'; then
    printf '%s\n' 'test failed: BUILD_REF appeared unexpectedly' >&2
    exit 1
fi
```

Muss der Ablauf ohne `BUILD_REF` stoppen, lassen Sie auch den lokalen Starter mit `${BUILD_REF:?BUILD_REF is required}` abbrechen. Die entfernte Prüfung bleibt nötig, weil sie die Übertragung und eine Serverablehnung erkennt.

Köder sollten jedes gefundene Muster abdecken und offensichtlich erfunden sein. Verwenden Sie nie echte Zugangsdaten, denn ein Fehler könnte sie beim Nachweis des Problems protokollieren.

Ein erfolgreicher Lauf beweist nicht, dass keine denkbare Variable passieren kann. Verbinden Sie ihn mit zwei statischen Prüfungen: `ssh -G` darf nur genaue `SendEnv`-Namen zeigen, `sshd -T -C` nur erwartete `AcceptEnv`-Namen. Bei `*` oder `?` kann keine Testmatrix künftige Namen aufzählen.

Führen Sie den Test aus jedem unterschiedlichen Starter aus. Entwickler-Shell, CI, Editor-Aufgabe und autonomer Agent können dasselbe Programm mit anderen Umgebungen und Pfaden starten. Schreiben Sie den `-F`-Pfad in den Starter statt in einen interaktiven Alias.

Den Endwert zu sehen belegt den SSH-Beitrag nicht. Setzt `/etc/profile` bereits `DEPLOY_REGION=us-east-1`, kann der Test trotz Serverablehnung bestehen. Eindeutige Marker und der Test mit fehlender Eingabe trennen echte Weitergabe von einem entfernten Ersatzwert.

Der Test behauptet nicht, die gesamte entfernte Umgebung enthalte nur drei Variablen. Eine normale Sitzung erhält auch `HOME`, `USER`, `SHELL`, `PATH` und SSH-Metadaten; weitere Schichten können Werte ergänzen. Geprüft wird der Client-Beitrag. Die Serverbasis braucht eine eigene Prüfung.

## Die Befehlserzeugung kann SendEnv vollständig umgehen

Ein leeres `SendEnv` hindert die lokale Shell nicht daran, Variablen in die entfernte Befehlszeichenkette einzusetzen. Das ist ein anderer Datenpfad:

```sh
ssh deploy-prod "release '$TENANT' '$TOKEN'"
```

Die lokale Shell ersetzt beide Werte, bevor `ssh` startet. Sie reisen in der verschlüsselten Befehlsanfrage statt in einer `env`-Anfrage, daher kann `AcceptEnv` sie nicht ablehnen. Je nach Starter erscheinen sie auch in Prozessansichten, Verlauf, CI-Protokollen oder Fehlermeldungen.

Dieses Präfix ändert die Umgebung des lokalen SSH-Prozesses, überschreitet die Grenze aber nur bei Auswahl des Namens:

```sh
DEPLOY_REGION=west ssh -F ./deploy-ssh.conf deploy-prod /usr/local/bin/release
```

Teams verwechseln diese Fälle häufig. Die Anwesenheit beim Start belegt keine Umgebungsweitergabe, und ein abgeschaltetes `SendEnv` belegt nicht, dass eine Hülle den Wert nicht in Argumente oder Standardeingabe eingesetzt hat. Verfolgen Sie den wirklichen Kanal.

Entfernter Startcode bildet weitere Quellen. Shell, `/etc/environment`, PAM, erzwungener Befehl, `sudo`, Dienstverwaltung oder Container können Werte nach der SSH-Annahme entfernen, ersetzen oder ergänzen. Fehlt ein Marker, prüfen Sie `ssh -vvv`, erlaubte Serverprotokolle und einen kleinen Befehl vor der Anwendungshülle. Erweitern Sie `AcceptEnv` nicht blind.

`sudo` braucht eine eigene Prüfung. Die Richtlinie kann die Umgebung des privilegierten Kindes löschen oder bewahren, doch der Wert war bereits in der nicht privilegierten SSH-Sitzung und konnte von Skripten gesehen werden. Konfigurieren Sie beide Ebenen getrennt.

Der entfernte Rechner ist keine passive Leitung. Wer das Konto kontrolliert, kann meist seine Umgebung ausgeben, und Administratoren kontrollieren die Maschine. Darf der Rechner einen Wert nie erfahren, senden Sie ihn in keiner Form über SSH.

Vermeiden Sie vollständige `env`-Ausgaben in normalen Protokollen. Erfassen Sie bei einer genehmigten Prüfung zuerst Namen und zeigen Sie Werte nur für erfundene Marker.

## Von Agenten gestartetes SSH braucht eine kleinere Prozessgrenze

Ein autonomer Agent erbt oft die Umgebung des Terminals, Editors oder Orchestrators. Sie wurde für einen Menschen mit mehreren Repositories und Konten zusammengestellt, nicht für eine einzelne entfernte Aktion. Ihre Weitergabe liefert dem Agenten zusätzlichen Kontext und entfernten Werkzeugen ungeprüfte Eingaben.

Starten Sie den Ablauf mit einer ausdrücklichen lokalen Umgebung und einer ausdrücklichen SSH-Datei. Eine kleine Hülle kann die zwei veränderlichen Werte verlangen, alles andere verwerfen und nur die Client-Bedürfnisse wiederherstellen:

```sh
#!/bin/sh
set -eu
: "${DEPLOY_REGION:?DEPLOY_REGION is required}"
: "${BUILD_REF:?BUILD_REF is required}"

exec env -i \
  HOME="$HOME" \
  PATH='/usr/bin:/bin:/usr/sbin:/sbin' \
  DEPLOY_REGION="$DEPLOY_REGION" \
  BUILD_REF="$BUILD_REF" \
  ssh -F ./deploy-ssh.conf deploy-prod /usr/local/bin/release
```

Passen Sie `PATH` und Eingaben an das Betriebssystem an und halten Sie die Liste ausdrücklich. `HOME` bleibt im Beispiel, weil OpenSSH known_hosts und die Identitätsdatei benötigen kann. Liefert ein verwalteter Starter diese Pfade anders, entfernen Sie auch `HOME`.

Für agentengesteuertes SSH auf einem Mac kann Sallyport den SSH-Schlüssel in seinem verschlüsselten Tresor halten und die Aktion über `sp-ssh` ausführen, ohne dem Agenten den Schlüssel zu geben. Diese Verwahrung ersetzt jedoch keinen genauen Umgebungsvertrag um den erlaubten Befehl.

Geben Sie lokale Cloud-Zugangsdaten nicht als Abkürzung weiter. Geben Sie der entfernten Last eine eigene begrenzte Identität oder verwenden Sie ein Gateway, das die Zugangsdaten hält. Das Kopieren einer geerbten Identität verbindet zwei Vertrauensgrenzen und erschwert den Widerruf.

## Halten Sie den Vertrag nach Änderungen ausführbar

Pakete ergänzen Standardwerte, Administratoren fassen Fragmente zusammen und Abläufe erhalten neue Eingaben. Eine Regel in Prosa erkennt diese Drift nicht. Prüfen Sie die eigene Client-Datei, das Serverkonto und den Ködertest gemeinsam.

Führen Sie den Test nach Änderungen an folgenden Stellen aus:

- SSH-Client- oder Betriebssystempakete;
- Nutzer- und Systemeinbindungen;
- `sshd_config`, PAM, Shell-Startdateien oder erzwungene Befehle;
- Agentenstarter, CI, Dienstverwaltung oder Containerabbild;
- Liste der erforderlichen Eingaben.

Behandeln Sie eine neue Variable wie eine Schnittstellenänderung. Dokumentieren Sie Bedarf, Eigentümer des Werts, empfindlichen Kontext und den Test ihrer Abwesenheit an anderen Stellen. Fehlen diese Antworten, übergeben Sie einen validierten Befehlswert oder ändern Sie das Design statt einen Platzhalter zu erweitern.

Machen Sie Fehler deutlich. Eine Bereitstellung, die nach einem Übertragungsfehler unbemerkt auf einen entfernten Standard zurückfällt, ist schwerer zu untersuchen und leichter falsch zu verwenden als ein Abbruch. Pflichtwerte müssen am lokalen Starter und am entfernten Einstieg scheitern.

Prüfen Sie zuletzt auch das entfernte Konto. Eine perfekte `SendEnv`-Liste schützt kein Konto, das beliebige Shells starten, Umgebungen anderer Nutzer lesen oder eigene Startdateien ändern kann. Machen Sie den Kanal genau, belegen Sie sein Verhalten und begrenzen Sie die Befehlsrechte.
