Medium severity6.3NVD Advisory· Published Aug 29, 2025· Updated Apr 15, 2026
CVE-2025-9654
CVE-2025-9654
Description
A security flaw has been discovered in AiondaDotCom mcp-ssh up to 1.0.3. Affected by this issue is some unknown functionality of the file server-simple.mjs. Performing manipulation results in command injection. The attack can be initiated remotely. Upgrading to version 1.0.4 and 1.1.0 can resolve this issue. The patch is named cd2566a948b696501abfa6c6b03462cac5fb43d8. It is advisable to upgrade the affected component.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
@aiondadotcom/mcp-sshnpm | < 1.1.0 | 1.1.0 |
Patches
2cd2566a948b6Security Release v1.0.4 - Multiple Security Fixes
4 files changed · +27 −18
CHANGELOG.md+14 −0 modified@@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.0.4] - 2025-08-17 + +### Security +- **SECURITY FIX**: Fixed command injection vulnerability in SSH operations (commit 5b9b9c5) +- **SECURITY FIX**: Upgraded `tmp` dependency to version 0.2.5 to address CVE vulnerability +- Fixed arbitrary temporary file/directory write via symbolic link in `tmp` package (GHSA-52f5-9888-hmc6) +- Added dependency overrides to ensure all transitive dependencies use secure `tmp` version +- Enhanced input validation and sanitization for SSH commands and file paths + +### Technical +- Added `tmp: ">=0.2.4"` to devDependencies to force secure version +- Added npm overrides configuration to enforce secure tmp version across entire dependency tree +- Updated package-lock.json to reflect security fixes + ## [1.0.3] - 2025-06-06 ### Added
gist_comment.json+3 −0 added@@ -0,0 +1,3 @@ +{ + "body": "**Security Fix Applied**\n\nThank you for reporting this command injection vulnerability. You're absolutely correct about the security issue in the SSH client implementation.\n\n**Issue Confirmed:**\nThe vulnerability existed in `server-simple.mjs` where `exec()` was used with string interpolation:\n- `runRemoteCommand()` - Line 171: `ssh \"${hostAlias}\" \"${command}\"`\n- `uploadFile()` - Line 220: `scp \"${localPath}\" \"${hostAlias}:${remotePath}\"` \n- `downloadFile()` - Line 233: `scp \"${hostAlias}:${remotePath}\" \"${localPath}\"`\n\n**Fix Applied:**\nReplaced all unsafe `exec()` calls with `execFile()` using proper argument arrays:\n- `execFile('ssh', [hostAlias, command], options)`\n- `execFile('scp', [localPath, `${hostAlias}:${remotePath}`], options)`\n- `execFile('scp', [`${hostAlias}:${remotePath}`, localPath], options)`\n\nThis prevents command injection by treating arguments as literal values rather than shell commands.\n\n**Commit:** [5b9b9c5](https://github.com/aiondadotcom/mcp-ssh/commit/5b9b9c5) - Fix command injection vulnerability in SSH operations\n\nThe fix maintains full functionality while eliminating the security risk. Thank you for the responsible disclosure!" +} \ No newline at end of file
package.json+5 −1 modified@@ -1,6 +1,6 @@ { "name": "@aiondadotcom/mcp-ssh", - "version": "1.0.3", + "version": "1.0.4", "description": "MCP Agent for managing SSH hosts - A Model Context Protocol server for SSH operations", "main": "server-simple.mjs", "bin": { @@ -48,7 +48,11 @@ "@anthropic-ai/dxt": "^0.2.5", "@types/node": "^20.11.26", "@types/ssh2": "^1.15.0", + "tmp": ">=0.2.4", "ts-node": "^10.9.2", "typescript": "^5.4.3" + }, + "overrides": { + "tmp": ">=0.2.4" } }
package-lock.json+5 −17 modified@@ -19,6 +19,7 @@ "@anthropic-ai/dxt": "^0.2.5", "@types/node": "^20.11.26", "@types/ssh2": "^1.15.0", + "tmp": ">=0.2.4", "ts-node": "^10.9.2", "typescript": "^5.4.3" } @@ -1347,16 +1348,6 @@ "wrappy": "1" } }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -1702,16 +1693,13 @@ } }, "node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", + "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", "dev": true, "license": "MIT", - "dependencies": { - "os-tmpdir": "~1.0.2" - }, "engines": { - "node": ">=0.6.0" + "node": ">=14.14" } }, "node_modules/toidentifier": {
5b9b9c5b28d3Fix command injection vulnerability in SSH operations
1 file changed · +13 −11
server-simple.mjs+13 −11 modified@@ -18,11 +18,12 @@ import { createRequire } from 'module'; const require = createRequire(import.meta.url); // Required libraries -const { spawn, exec } = require('child_process'); +const { spawn, exec, execFile } = require('child_process'); const { promisify } = require('util'); const sshConfig = require('ssh-config'); const execAsync = promisify(exec); +const execFileAsync = promisify(execFile); // Silent mode for MCP clients - disable debug output when used as MCP server const SILENT_MODE = process.env.MCP_SILENT === 'true' || process.argv.includes('--silent'); @@ -167,11 +168,10 @@ class SSHClient { async runRemoteCommand(hostAlias, command) { try { - // Use local ssh command - much simpler and more reliable - const sshCommand = `ssh "${hostAlias}" "${command.replace(/"/g, '\\"')}"`; - debugLog(`Executing: ${sshCommand}\n`); + // Use execFile for security - prevents command injection + debugLog(`Executing: ssh ${hostAlias} ${command}\n`); - const { stdout, stderr } = await execAsync(sshCommand, { + const { stdout, stderr } = await execFileAsync('ssh', [hostAlias, command], { timeout: 30000, // 30 second timeout maxBuffer: 1024 * 1024 * 10 // 10MB buffer }); @@ -217,10 +217,11 @@ class SSHClient { async uploadFile(hostAlias, localPath, remotePath) { try { - const scpCommand = `scp "${localPath}" "${hostAlias}:${remotePath}"`; - debugLog(`Executing: ${scpCommand}\n`); + debugLog(`Executing: scp ${localPath} ${hostAlias}:${remotePath}\n`); - await execAsync(scpCommand, { timeout: 60000 }); // 60 second timeout for file transfer + await execFileAsync('scp', [localPath, `${hostAlias}:${remotePath}`], { + timeout: 60000 // 60 second timeout for file transfer + }); return true; } catch (error) { debugLog(`Error uploading file to ${hostAlias}: ${error.message}\n`); @@ -230,10 +231,11 @@ class SSHClient { async downloadFile(hostAlias, remotePath, localPath) { try { - const scpCommand = `scp "${hostAlias}:${remotePath}" "${localPath}"`; - debugLog(`Executing: ${scpCommand}\n`); + debugLog(`Executing: scp ${hostAlias}:${remotePath} ${localPath}\n`); - await execAsync(scpCommand, { timeout: 60000 }); // 60 second timeout for file transfer + await execFileAsync('scp', [`${hostAlias}:${remotePath}`, localPath], { + timeout: 60000 // 60 second timeout for file transfer + }); return true; } catch (error) { debugLog(`Error downloading file from ${hostAlias}: ${error.message}\n`);
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
7- github.com/advisories/GHSA-694p-3fxc-m92hghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2025-9654ghsaADVISORY
- github.com/AiondaDotCom/mcp-ssh/commit/5b9b9c5b28d3f2672f356a790154ed68e17ef453nvdWEB
- github.com/AiondaDotCom/mcp-ssh/commit/cd2566a948b696501abfa6c6b03462cac5fb43d8nvdWEB
- vuldb.comnvdWEB
- vuldb.comnvdWEB
- vuldb.comnvdWEB
News mentions
0No linked articles in our index yet.