From 4feaba1bb12dd023e3e7383f9f1cecf80f0b63c8 Mon Sep 17 00:00:00 2001 From: nexxo Date: Mon, 3 Aug 2026 19:19:54 +0200 Subject: [PATCH] Eine occ-Befehlsform, deren Wert erst im Container eingesetzt wird config:system:set will den Wert als Argument. Setzte ihn die aeussere Shell ein, stuende das SMTP-Passwort in der Prozessliste der Kunden-VM. Mit `sh -c` im Container steht dort nur der Variablenname. Im Kopfkommentar steht ausdruecklich, dass das Hygiene ist und kein Schutz: Nextcloud legt den Wert danach im Klartext in config.php ab. Co-Authored-By: Claude Opus 5 --- app/Support/NextcloudOcc.php | 35 ++++++++++++++++++++++++++++++ tests/Feature/NextcloudOccTest.php | 26 ++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 tests/Feature/NextcloudOccTest.php diff --git a/app/Support/NextcloudOcc.php b/app/Support/NextcloudOcc.php index b638e6b..439dace 100644 --- a/app/Support/NextcloudOcc.php +++ b/app/Support/NextcloudOcc.php @@ -72,4 +72,39 @@ final class NextcloudOcc { return 'cd '.self::DIRECTORY.' && docker compose exec -T -u '.self::USER.' app '.$arguments; } + + /** + * Wie command(), aber der Wert wird erst von der Shell IM Container + * eingesetzt. + * + * command() taugt fuer `--password-from-env`, wo occ selbst die + * Umgebungsvariable liest. `config:system:set` kann das nicht: es will den + * Wert als Argument. Setzte die aeussere Shell ihn ein, stuende das + * Passwort in der Prozessliste der KUNDEN-VM — dort, wo jeder mit einer + * Shell auf der Maschine `ps` ausfuehren kann. So steht es nur in der des + * Containers. + * + * EHRLICHERWEISE ist das Hygiene, kein Schutz: Nextcloud legt + * `mail_smtppassword` anschliessend im Klartext in config/config.php ab. + * Wer auf der Maschine eine Shell hat, liest es dort. Die eigentliche + * Eingrenzung liegt woanders — das Versandkonto kann nur senden, und der + * Versandport nimmt nur die eigenen Hostadressen an. Diese Methode senkt + * die Gelegenheit, sie beseitigt sie nicht. + * + * @param array $env + */ + public static function commandExpandingEnv(string $arguments, array $env): string + { + $assignments = ''; + $forwards = ''; + + foreach ($env as $name => $value) { + $assignments .= $name.'='.escapeshellarg($value).' '; + $forwards .= '-e '.$name.' '; + } + + return 'cd '.self::DIRECTORY.' && '.$assignments + .'docker compose exec -T -u '.self::USER.' '.$forwards + .'app sh -c '.escapeshellarg('php occ '.$arguments); + } } diff --git a/tests/Feature/NextcloudOccTest.php b/tests/Feature/NextcloudOccTest.php new file mode 100644 index 0000000..686d6c1 --- /dev/null +++ b/tests/Feature/NextcloudOccTest.php @@ -0,0 +1,26 @@ + 'geheim'], + ); + + // Das Geheimnis steht als Zuweisung da (die aeussere Shell reicht es + // durch), aber der occ-Aufruf traegt nur den VARIABLENNAMEN — eingesetzt + // wird er von der sh INNERHALB des Containers. + expect($befehl)->toContain("CLUPILOT_SMTP_PW='geheim'") + ->and($befehl)->toContain('-e CLUPILOT_SMTP_PW') + ->and($befehl)->toContain('sh -c') + // Entscheidend: hinter `php occ` steht der Name, nicht der Wert. + ->and(substr($befehl, strpos($befehl, 'sh -c')))->not->toContain('geheim'); +}); + +it('haelt sich an dasselbe Verzeichnis und denselben Benutzer wie command()', function () { + $befehl = NextcloudOcc::commandExpandingEnv('status', []); + + expect($befehl)->toStartWith('cd '.NextcloudOcc::DIRECTORY) + ->and($befehl)->toContain('-u '.NextcloudOcc::USER); +});