BoundBench

Linux MCP Server (RHEL Lightspeed)

MCP server for read-only Linux system administration and diagnostics on RHEL-based systems, locally or over SSH.

github.com/rhel-lightspeed/linux-mcp-server · 2026-10-04 · 11e3035

Defense-in-depth score

5.6 / 10

Moderate

As shipped, Linux MCP Server only exposes fixed, genuinely read-only diagnostic commands, run as argument lists with timeouts and size caps, so it cannot change your systems. The main risk is what it can read and where it can reach: read_file opens any file your account can read, including SSH private keys, and the model can point any tool at any host name using your own SSH identity, which also gives a hijacked session a way to leak what it read. Its strong authorization policy and the sandbox for the optional script-execution mode are opt-in, and that script mode is much weaker than the default.

Key gaps (1)

  1. In the opt-in run_script toolset the model's own readonly flag selects the sandbox profile, so modifying scripts run as root via sudo systemd-run with host networking, and the sandbox is not a complete boundary. C4 · Code-execution isolation

Criteria

C1 Identity & least privilege

Moderate 0.50 / 1.00

In its default local setup the server runs as whoever launched it and, with no policy file, the authorization middleware allows every tool call on every host. Remote calls use the operator's own SSH identity (default keys or agent) against any host name the model supplies, and local commands inherit the server's full environment. The project does ship a real, deterministic authorization layer: a YAML policy that maps tool, host and token claims to deny, local, or SSH with a specific per-rule key and user, and denies anything unmatched. It is opt-in, so it can only lift this criterion to the off-by-default ceiling.

C2 Approval gates

Moderate 0.65 / 1.00

As a tool server, the host owns the approval prompt, so this rates what the server tells the host. In the default 'fixed' toolset every tool is genuinely read-only and annotated readOnlyHint, the server refuses calls to tools outside the configured toolset, and nothing it exposes changes state, so a wrongly approved call can't change anything. The opt-in run_script toolset is weaker: the 'read-only' run_script tool trusts a flag the model sets (checked by an LLM gatekeeper), run_script_with_confirmation executes immediately on the server side; approval enforcement on the app-only script path is also not complete.

C3 Tool & action scoping

Moderate 0.55 / 1.00

Tools are narrow and well built in shape: each runs a fixed command as an argument list (no shell locally, shell-quoted over SSH), with typed parameters, numeric bounds, regex-validated PCP names, and a resolved-path allowlist for read_log_file. But path checking is shallow: read_file and the listing tools accept any absolute path without '..', so the model can read any file the user can read (SSH keys, cloud credentials), which makes the log allowlist moot. The host argument is any string with no allowlist, and other argument validation is not strict.

C4 Code-execution isolation

Minimal 0.20 / 1.00

The default read-only toolset never runs model-written code: every command is a fixed argument list. Code execution exists only in the opt-in run_script toolset, which is therefore what this criterion rates. There, scripts flagged read-only by the model run under sudo systemd-run with a read-only filesystem and no network, but scripts flagged as modifying run as root with only PrivateTmp and NoNewPrivileges; the wrapper is also not a complete boundary. Because the score reflects that opt-in path, it says little about the default install, which has no execution surface.

C5 Untrusted input blast radius

Minimal 0.30 / 1.00

The server feeds the model content that others can write: journal entries, log files, service output, process command lines and arbitrary file contents. Some tools return structured models (log entries with their unit or path), but read_file and several status tools return plain text with no marker that it is untrusted. In the default mode a hijacked model can read local secrets such as SSH keys and then leak them through the host name argument, which triggers DNS lookups and SSH connection attempts to any name it chooses. No tool can change state, so the worst case is data exfiltration, not destruction.

C6 Memory, context & configuration integrity

N/A · full credit 1.00 / 1.00

The server keeps no memory, conversation store or retrieval index, and reads no instruction or configuration files from a working directory. Settings come only from LINUX_MCP_* environment variables and command-line flags (pydantic-settings with no .env file), and the optional policy file comes from an explicit operator-supplied path. Validated scripts are held in memory only for the life of the process.

C7 Third-party extensions

N/A · full credit 1.00 / 1.00

The server loads no third-party code at runtime: no plugin system, no MCP client, no package installs on the model's behalf, and no model files. The MCP App HTML/JS is read from the package's own resources. A _vendor directory lets downstream packagers bundle dependencies at build time, which is ordinary supply chain rather than runtime extension loading.

C8 Secrets & sensitive-data protection

Minimal 0.38 / 1.00

The few secrets the server holds (SSH key passphrase, OAuth client secrets) are SecretStr values, there is no telemetry, and tool-call logging redacts any parameter whose name looks sensitive. But nothing stops secrets reaching the model: read_file returns any file the user can read, including private SSH keys and cloud credential files, and local commands inherit the server's full environment, including gatekeeper API keys when that toolset is enabled.

C9 Audit & traceability

Moderate 0.50 / 1.00

Every one of the server's 30 tools is wrapped by a logging decorator that writes a structured record (tool, sanitized arguments, host, status, duration, timestamp) to rotating text and JSON files under ~/.local/share, and remote commands are logged with their exact command line and exit code. Local commands are logged only at debug level, and in the default local mode there is no user identity and authorization decisions are logged only at debug. The files are ordinary user-writable files kept for ten days.

C10 Limits & kill switch

Moderate 0.55 / 1.00

Every command the server runs, locally or over SSH, has a 30-second default timeout; file reads are capped at 1 MiB, log and journal reads at 10,000 lines, and listings at depth one. There are no rate or concurrency limits, some outputs (process list, service list) are unbounded, and a local timeout kills only the direct child process, not any processes it spawned.