Root escalation: --persistent ownership check misses symlinks and writable parent dirs #1

Closed
opened 2026-08-11 10:25:34 +00:00 by aav · 0 comments
Owner

install_daemon (src/setup.rs:373, and safe_to_run_as_root at src/setup.rs:346) checks only the binary file's uid/mode, not the path used to reach it. A root-owned binary reached via a user-owned symlink, or sitting in a user-writable directory, passes the check, and the LaunchDaemon plist then records the swappable path. The config is canonicalized but its parent directory's writability is likewise unchecked.

Failure scenario: user runs sudo ~/bin/silta setup --persistent where ~/bin/silta is a symlink to root-owned /usr/local/bin/silta (or the binary is root-owned 755 inside a user-writable directory). fs::metadata follows the link, the check passes, and the plist stores the user-controlled path. The user later replaces the symlink target or renames a new file into place (directory write suffices, no root needed), and arbitrary code runs as root at the next boot -- exactly the escalation the check exists to prevent.

Fix direction: resolve the real path (canonicalize the binary), and verify every path component up to root is root-owned and not group/world-writable, for both binary and config.

Source: high-effort code review, CONFIRMED. Area: setup.

`install_daemon` (src/setup.rs:373, and `safe_to_run_as_root` at src/setup.rs:346) checks only the binary file's uid/mode, not the path used to reach it. A root-owned binary reached via a user-owned symlink, or sitting in a user-writable directory, passes the check, and the LaunchDaemon plist then records the swappable path. The config is canonicalized but its parent directory's writability is likewise unchecked. **Failure scenario:** user runs `sudo ~/bin/silta setup --persistent` where `~/bin/silta` is a symlink to root-owned `/usr/local/bin/silta` (or the binary is root-owned 755 inside a user-writable directory). `fs::metadata` follows the link, the check passes, and the plist stores the user-controlled path. The user later replaces the symlink target or renames a new file into place (directory write suffices, no root needed), and arbitrary code runs as root at the next boot -- exactly the escalation the check exists to prevent. **Fix direction:** resolve the real path (canonicalize the binary), and verify every path component up to root is root-owned and not group/world-writable, for both binary and config. Source: high-effort code review, CONFIRMED. Area: setup.
aav self-assigned this 2026-08-11 10:27:24 +00:00
aav closed this issue 2026-08-11 11:03:14 +00:00
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
carvers/silta#1
No description provided.