clitunes is a local desktop application. It makes outbound network connections (HTTPS to radio-browser.info, HTTP/HTTPS to radio streams) but exposes no listening network ports. The only IPC surface is a Unix domain socket for daemon control.
The daemon's control socket is protected by three layers:
-
Umask-atomic bind (SEC-001). Before
bind(2), the process setsumask(0o177)so the socket inode is created with mode0600atomically. There is no TOCTOU window between bind and chmod. -
Runtime directory permissions. The socket lives under
$XDG_RUNTIME_DIR/clitunes/(Linux, mode 0700 by systemd-logind) or$TMPDIR/clitunes-$USER/(macOS, mode 0700 created by clitunes). Even if the socket mode were wrong, the parent directory blocks traversal by other UIDs. -
Peercred UID gate. On every
accept(2), the daemon queries the peer's UID viaSO_PEERCRED(Linux) orLOCAL_PEERCRED(macOS). If the peer UID does not matchgetuid(), the connection is closed immediately — before any data is read. This is the last line of defence if both umask and directory permissions somehow fail.
The flock at $runtime_dir/clitunesd.lock prevents a second daemon from
binding to the same socket path. Unlike pidfile-based locking, the
kernel releases the flock on process death so a crashed daemon cannot
leave a stale lock behind.
Radio station metadata and ICY stream titles pass through the
UntrustedString sanitiser (clitunes-core) before reaching the TUI.
The sanitiser strips C0 controls (except whitespace), C1 codepoints,
ESC sequences, OSC sequences (including clipboard/title attacks), and
CSI sequences. This prevents a malicious radio stream from injecting
terminal control sequences into the user's display.
The control bus uses LinesCodec::new_with_max_length(65_536). A
client sending a line longer than 64KB is disconnected immediately.
Without this limit, a single malicious pre-peercred connection could OOM
the daemon by sending a multi-gigabyte line.
Each connected client has a per-client mpsc channel with capacity 64.
If a client falls behind (doesn't read events), the channel fills and
the daemon disconnects that client. Other clients are unaffected.
broadcast::Sender is not used anywhere (D14) because it silently
drops messages, hiding backpressure failures.
cargo-deny runs in CI with a conservative license allow-list and
advisory database checks. Known advisories are documented with
justification in deny.toml. This narrows (but does not eliminate)
supply chain risk.
Root can read any socket, attach to any process, and access any file. clitunes does not attempt to defend against a compromised root account.
clitunes makes outbound HTTPS connections only (radio-browser.info discovery, radio stream URLs). It does not listen on any network port. A network attacker who can MITM the HTTPS connection could serve malicious stream data, but the audio decoder (symphonia) is a memory-safe Rust library and stream metadata is sanitised before display.
clitunes trusts the system CA store (via rustls + webpki-roots) for HTTPS connections to radio-browser.info. Compromise of a trusted CA could allow a MITM to serve a malicious mirror list. The blast radius is limited to radio stream discovery; local playback is unaffected.
cargo-deny reduces the surface by flagging advisories and restricting licenses, but a zero-day in any transitive dependency could compromise the process. This is inherent to software supply chains.
If the user's own account is compromised, the attacker has the same UID and passes the peercred check. clitunes does not sandbox itself beyond the user's own privileges. The threat model assumes the user account is trusted.
struct ucred cred;
socklen_t len = sizeof(cred);
getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cred, &len);
// cred.uid, cred.gid, cred.pidThe kernel fills the ucred at connection time. The values cannot be
spoofed by the peer.
// PID
pid_t pid;
socklen_t len = sizeof(pid);
getsockopt(fd, SOL_LOCAL, LOCAL_PEERPID, &pid, &len);
// UID + GID
struct xucred cred;
cred.cr_version = XUCRED_VERSION;
socklen_t len = sizeof(cred);
getsockopt(fd, SOL_LOCAL, LOCAL_PEERCRED, &cred, &len);
// cred.cr_uid, cred.cr_groups[0]stat $XDG_RUNTIME_DIR/clitunes/clitunesd.sock
# Should show: srw------- (mode 0600)
ls -ld $XDG_RUNTIME_DIR/clitunes/
# Should show: drwx------ (mode 0700)