Files
ServerKit/builtin-extensions
Juan DenisandClaude Opus 5 b51d9c2018 fix(services): close the rest of the bare-name sbin exec class
The ufw fix repaired every run_privileged caller centrally, but three sites
reached subprocess by other routes and were broken the same way. All are
"$PATH omits sbin + the panel runs as root, so nothing prepends sudo to
resolve it".

- run_command() got the same argv[0] resolution as privileged_cmd. It does no
  privilege escalation, so nothing else would ever find these commands.
- nginx_advanced_service.test_config() ran `nginx -t` (/usr/sbin/nginx) via
  run_command, so it raised FileNotFoundError and reported every config
  invalid. It also returned valid=True unconditionally, ignoring the exit code
  entirely — so when it DID run, a broken config passed. Now run_privileged and
  the returncode is checked. reload_nginx() likewise reports a failed reload
  instead of swallowing it.
- dovecot_service.get_status() detected dovecot with `which`, which searches
  $PATH only and false-negatives on /usr/sbin/dovecot, then read the version by
  bare name under a shared except. Now is_command_available() + a separate try,
  so a version read that fails cannot unsay "installed". Patched in both the
  builtin-extensions source and the app/plugins live copy.
- SecurityService.get_lynis_status() inferred presence solely from exec'ing
  `lynis --version`; presence and version are now separate questions.

Adds test_sbin_command_guard.py so this cannot come back: an AST scan fails CI
on any raw subprocess call using a known sbin-resident command by bare name
(it caught the dovecot site), plus per-command proof that both helpers resolve
under the exact PATH the panel unit ships.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 09:37:59 -04:00
..