Commit ae0cbcd
fix(security): harden the exec/FS trust boundary in server_actions (#59)
Three injection classes were reachable from GUI-supplied values:
1. Remote command injection. The SSH paths in executeAction/streamLogs/
getServerStatus built 'ssh <host> podman ... <container_name>' with no
protection; ssh concatenates its remote args into one string the remote
login shell re-parses, so a container_name like 'foo; rm -rf /' ran the
rm. (executeSSH existed but was unused AND its own '--' does not stop
remote-shell reparsing — its doc comment was wrong.)
2. SSH option injection. An unvalidated host such as '-oProxyCommand=evil'
is read by ssh as an option.
3. Path traversal. run_script accepted 'scripts/../../etc/x' (prefix check
only); write_server_config interpolated a raw profile_id into a path; and
Settings.xml element text was interpolated with no escaping (operator
attrs escaped only '"').
Fixes:
- Allowlist validators isSafeContainerName / isSafeHost / isSafeProfileId
reject every shell metacharacter and path-traversal char at the boundary.
- Single SSH path: the three callers build a bare command and route through
dispatch() -> executeSSH, which now POSIX-single-quotes every remote arg
(shellQuoteInto) as defence-in-depth; false doc comment corrected.
- run_script also rejects '..' components and absolute paths.
- write_server_config validates profile_id and XML-escapes all five entities
in every interpolated value (xmlEscapeInto/Alloc).
- parseAndDispatch converts validation errors into a structured failure
result instead of propagating.
- 10 adversarial unit tests (injection payloads, traversal, quoting,
escaping). Grep-gate: no inline 'ssh' arg-building remains. 150 tests green.
Also adds timeout-minutes to push-email-notify.yml (Hypatia workflow_audit).
Claude-Session: https://claude.ai/code/session_01TaWWedv6VQqeZaPvc94keN
Co-authored-by: Claude <noreply@anthropic.com>1 parent 8c72689 commit ae0cbcd
2 files changed
Lines changed: 319 additions & 73 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
| 16 | + | |
16 | 17 | | |
17 | 18 | | |
18 | 19 | | |
| |||
0 commit comments