Skip to content

Releases: AiondaDotCom/mcp-ssh

v1.3.9 — security release

Choose a tag to compare

@ferraro ferraro released this 10 Aug 14:30

Security release. Everyone on 1.3.8 or earlier should update, in particular anyone running the Claude Desktop extension — that install path had no update until now.

Security

Two issues, both reachable by an attacker who can influence the tool arguments the model produces — i.e. through prompt injection in any untrusted content the model reads. This project's threat model treats the LLM as untrusted, so that is an assumed adversary, not a hypothetical one.

[High] SSH config poisoning escalated remote execution to local RCEGHSA-pj6m-cx2p-44gh

~/.ssh/config is the file that defines which hosts may be reached, and ssh executes any ProxyCommand it finds there locally through /bin/sh. Nothing stopped downloadFile from writing to it, so three in-contract tool calls chained into code execution on the user's own machine. Downloads into the SSH directory are now refused, accounting for .., symlinks (including ones whose target does not exist yet), a leading ~, and case-insensitive filesystems.

[High] A colon in hostAlias sent scp to a host the allowlist never approvedGHSA-gpr2-2wqr-7rgp

scp splits its remote spec on the first colon while ssh never splits its destination, so an approved alias like a:b connected to a. The scp host is now bracketed. This also fixes a real bug: a bare IPv6 address silently targeted the wrong machine — 2001:db8::1 resolved to 0.0.7.209, because scp read 2001 as an IPv4 integer.

Also hardened: the askpass helper no longer sits at a predictable path (it is created exclusively inside a mkdtemp directory), and Include recursion is bounded against self-including configs.

Thanks to the reporter of GHSA-gpr2-2wqr-7rgp, whose insight — that a path argument changes meaning once a different program interprets it — prompted the review that found the rest.

Fixed

  • Windows/Claude Desktop: every SSH command failed with exit 255 and empty output, because the launcher's stripped environment omits %ProgramData% (#10)
  • Hosts declared under several aliases (Host docker-lxc hlab) were unreachable under any of their names (#12)
  • Host * !bastion defaults blocks were listed as connectable hosts
  • All 17 open npm audit advisories resolved

Changed

  • Ported to TypeScript: seven typed modules under src/, strict compiler, type-aware ESLint
  • CI runs on Linux and Windows across Node 20/22/24, with 100% coverage enforced as a build gate (201 tests)
  • The desktop bundle moved to the MCP Bundle toolchain and dropped its devDependencies: 81 MB → 3.7 MB

Installing the desktop extension

Download mcp-ssh-1.3.9.mcpb for current Claude Desktop versions. If your build only accepts the older extension, mcp-ssh-1.3.9.dxt is the same archive under the previous name.

Via npm: npm install -g @aiondadotcom/mcp-ssh@1.3.9

Release v1.3.8

Choose a tag to compare

@ferraro ferraro released this 14 Apr 16:30

Fix startup regression: start.sh, start-silent.sh, npm scripts and DXT manifest now invoke bin/mcp-ssh.js. Since 1.3.6 server.mjs no longer auto-runs main(), so these entry points exited immediately.

1.3.7 - Dependency security updates

Choose a tag to compare

@ferraro ferraro released this 11 Apr 16:20

Security maintenance

Resolves all open npm audit advisories by bumping transitive dependencies. npm audit --audit-level=high now reports zero vulnerabilities.

GHSAs resolved

Production dependency chain (@modelcontextprotocol/sdk → express → router → path-to-regexp):

These were not exploitable in practice because mcp-ssh uses the SDK over STDIO and never touches the HTTP routing code paths the advisories apply to — but they are fixed anyway.

Development dependency chain (vitest / test tooling):

  • hono — 6 advisories (prototype pollution, cookie handling, IP matching, path traversal, middleware bypass)
  • @hono/node-server — middleware bypass via repeated slashes
  • node-forge — 4 high-severity crypto advisories
  • brace-expansion — DoS via zero-step sequence
  • picomatch — method injection + ReDoS
  • vite — path traversal, server.fs.deny bypass, arbitrary file read

The vite fix required a minor bump of vitest and @vitest/coverage-v8 from 4.0.18 to 4.1.4.

Verification

  • npm audit --audit-level=high → 0 vulnerabilities
  • vitest run → 99/99 tests green

Upgrade

npm install -g @aiondadotcom/mcp-ssh@1.3.7 or update your client config to use npx @aiondadotcom/mcp-ssh@latest.

1.3.6 - Fix Windows startup (issue #8)

Choose a tag to compare

@ferraro ferraro released this 11 Apr 14:48

Bug fix

Fixes a silent startup failure when launching the server via bin/mcp-ssh.js on Windows MCP clients (e.g. Antigravity), which manifested as a failed to initialize: EOF error in the client.

Cause

server.mjs had an isMainModule heuristic that compared process.argv[1] against forward-slash path suffixes (/mcp-ssh.js, /server.mjs, /mcp-ssh). On Windows, process.argv[1] uses backslashes, so none of those endsWith checks matched and main() was never called. The process exited silently, and the MCP client saw STDIO close immediately.

Fix

The isMainModule heuristic has been removed entirely. bin/mcp-ssh.js now imports main() from server.mjs and calls it explicitly. This is the only real entry point and works identically on every platform.

Credit

Reported by @sdwru in #8.

Upgrade

npm install -g @aiondadotcom/mcp-ssh@1.3.6 or update your client config to use npx @aiondadotcom/mcp-ssh@latest.

1.3.5 - Security fix (high)

Choose a tag to compare

@ferraro ferraro released this 11 Apr 14:37

Security fix (high severity)

This release fixes a high-severity local RCE in the MCP server and ships several related hardenings. All users should upgrade.

What was vulnerable

A crafted hostAlias such as -oProxyCommand=... was passed to ssh/scp without an argument terminator. SSH interprets arguments starting with - as options regardless of position, so the option-injection caused SSH to execute the attacker-supplied ProxyCommand locally on the machine running the MCP server — before any network connection. This bypassed the documented protection of # @password: annotations and exposed local SSH keys, browser cookies, other MCP server credentials, and anything else readable by the server process.

A second local-RCE vector existed on Windows: spawn(..., { shell: true }) was used so that ssh.exe/scp.exe could be found via PATH. With shell: true, every argument is re-parsed by cmd.exe, so shell metacharacters (&, |, ^, >, ", ;, …) in hostAlias, command, localPath or remotePath would have been interpreted by cmd.exe and could have triggered arbitrary local command execution on Windows.

Threat model

The MCP server runs locally over STDIO, but the LLM driving it is not trusted: its tool arguments can be steered by prompt injection from any untrusted text in the conversation context (web pages, e-mails, repository files, output of other MCP servers). The attack does not require a malicious user — it requires only that the LLM ingests attacker-controlled text at any point.

What was fixed

  • Add -- argument terminator to all ssh/scp invocations.
  • Strict whitelist for hostAlias (^[A-Za-z0-9_.@:][A-Za-z0-9._@:-]*$) — rejects leading - and shell metacharacters.
  • Known-host check: every hostAlias must be defined in ~/.ssh/config (including Include directives) or present in ~/.ssh/known_hosts. The LLM can no longer reach arbitrary hostnames the user has not explicitly configured.
  • Resolve ssh.exe/scp.exe to absolute paths once at startup via PATH+PATHEXT walk on Windows; use shell: false everywhere.
  • expandIncludePath() now handles Windows drive-letter and UNC paths correctly and accepts ~\path with backslash separators.
  • Drop hard-coded DISPLAY=:0 from the askpass environment (POSIX/X11 assumption that could break Windows).
  • Documented threat model and trust boundaries in README.md.
  • Regression tests for option-injection, shell-metacharacter injection, unknown-host rejection, Include directives and known_hosts entries (99 tests, all green).

Affected versions

< 1.3.5

Fixed in

1.3.5

Credit

Reported by Pico (@piiiico) as part of an MCP server security audit. Thank you for the responsible disclosure.

Upgrade

npm install -g @aiondadotcom/mcp-ssh@1.3.5 or update your claude_desktop_config.json to use npx @aiondadotcom/mcp-ssh@latest.

Release v1.0.3 - Desktop Extension

Choose a tag to compare

@ferraro ferraro released this 15 Jul 07:26

MCP SSH Agent v1.0.3 - Desktop Extension

What's New

  • Desktop Extension Support: One-click installation for Claude Desktop
  • Fixed Configuration: Corrected manifest.json for reliable extension loading
  • Improved Stability: Native SSH command integration for maximum compatibility

Installation Options

Option 1: Desktop Extension (Recommended)

  1. Download the mcp-ssh-1.0.3.dxt file below
  2. Open Claude Desktop
  3. Go to Settings > Extensions
  4. Click "Install from file" and select the downloaded .dxt file
  5. Restart Claude Desktop

Option 2: Manual Configuration

Add to your Claude Desktop config:

{
  "mcpServers": {
    "mcp-ssh": {
      "command": "npx",
      "args": ["@aiondadotcom/mcp-ssh"]
    }
  }
}

Features

  • List and connect to SSH hosts from ~/.ssh/config
  • Execute remote commands securely
  • Upload/download files via SCP
  • Batch command execution
  • Host connectivity testing

Requirements

  • Node.js 14+
  • SSH client installed
  • Properly configured SSH keys

🤖 Generated with Claude Code