Email michael.groberman@icloud.com with subject [linux-mcp security], or open a private vulnerability advisory.
linux-mcp is a local MCP server speaking stdio JSON-RPC to a single MCP client (Claude Code, Cline, etc.). Trust boundary:
- Trusted: the MCP client. The server validates schemas and enforces hard limits on every call.
- Untrusted (defense in depth): anything reading the audit log, anything reading
/proc/<pid>/, the helper binaries themselves (we shell out to a curated list —mdfind/xdotool/wmctrl/ydotool/wtype/grim/scrot/maim/xclip/xsel/wl-clipboard/notify-send/zenity/kdialog— and these are upstream-maintained).
- No remote attack surface. stdio only. No listening sockets. No outbound network calls.
- Filesystem allow-list with symlink resolution. Every
fs_*tool canonicalises throughstd::fs::canonicalize(or write-mode parent-only canonicalisation when the leaf doesn't exist yet) before checking allow + deny roots. This is the explicit defense against the symlink-bypass that Desktop Commander's FAQ admits its allow-list does not prevent. - Default deny on system paths.
/proc,/sys,/dev,/boot,/etc,/var/lib,/var/log,/run,/usr/sbin,/sbin,/rootare denied by default and override any allow-listed parent. - Process exec is opt-in by binary basename.
LINUX_MCP_PROCESS_ALLOWis empty by default → everyprocess_*call is refused. To use it, the operator explicitly lists basenames (git,rg, etc.). Shell mode (shell=true) requires/bin/shto be in that list. - No
run_shell/eval_*escape hatches. Every tool is a named typed function with bounded inputs. - Hard caps:
fs_read10 MB,fs_write50 MB,fs_list5,000 entries,process_run1 MB stdout / 256 KB stderr / 30 s default (300 s max) timeout,type_text10,000 chars,wait_ms60,000 ms. process_killcross-user guard. Refuses pid 1 unconditionally and refuses any pid owned by a different uid unlessLINUX_MCP_PROCESS_KILL_ANY=1is set (acknowledging the operator's intent).- Audit log. Every tool call writes a JSONL line (timestamp, level, msg, meta) to
$XDG_STATE_HOME/linux-mcp/audit.log, rotated at 10 MB. No telemetry.
- Kernel-level privilege escalation, SELinux/AppArmor policy bugs, container escape — these are upstream concerns.
- Bugs in helper binaries (
xdotooletc.) — report upstream. - Side-channel disclosures via screenshot / clipboard / pasteboard contents — these are user-controlled.
- Built with
--releaseandlto = "thin"(inCargo.toml) - No
unsafeblocks added (runrg unsafebefore tagging) -
cargo auditclean -
cargo deny checkclean - Stripped symbols in release binary