🔴 Security release — upgrade recommended
Three reported advisories, all the same class of bug, all confirmed present in 3.8.4.
The v3.6.7 fix (CVE-2026-77383) introduced a centralized shellQuote() — and applied it to src/database-manager.js only. The parallel builders for backups and monitoring were never covered, so the same RCE stayed open in three other places.
GHSA-m793-whw6-f537 — critical — bypasses readonly / restricted
ssh_service_status and ssh_tail are read-only tools, so they stay enabled on servers you explicitly locked down. Neither quoted its arguments, and neither consulted the policy layer.
{ "name": "ssh_service_status",
"arguments": { "server": "prod", "services": ["nginx; id > /tmp/pwned; true"] } }buildServiceStatusCommand interpolated the service name unquoted six times; ssh_tail built tail -n ${lines} "${file}" | grep "${grep}" inside double quotes only, so $(...), backticks and a " breakout all executed. This defeated the exact control those modes exist to provide.
GHSA-796j-h5q5-jx6p — critical — ssh_db_dump
The stat command run after the dump interpolated outputFile raw. The dump itself had been fixed in v3.6.7; the line after it had not.
GHSA-qwwm-vrm9-4mw8 — high — every ssh_backup_* tool
src/backup-manager.js concatenated database, dbUser, dbPassword, dbHost, backupDir, paths and exclude into shell strings with no escaping — 0 uses of shellQuote across 9 builders, against 95 in the database module.
What changed
shellQuote()moved tosrc/shell-quote.jsand imported by every builder, so "did this quote its inputs?" has one answer instead of one per file. Applied acrossbackup-manager.js(54 call sites),health-monitor.js, and the remaining inline commands inindex.js.safeInteger()for numeric arguments that still land in command strings.buildProcessInfoCommandvalidates its PID, asbuildKillProcessCommandalways did.ssh_tailandssh_service_statusnow call the policy layer.
How it is verified
npm run test:backupinjection drives 340 combinations (builder × argument × payload) through a real /bin/sh, with the database and init binaries faked as no-ops and the shell utilities left real, asserting a canary file is never created. Verified by mutation: removing any single quote-call is caught.
Upgrade if you use ssh_backup_*, ssh_db_dump, ssh_service_status or ssh_tail — and especially if you rely on readonly or restricted mode. No configuration or API changes.
Full changelog: https://github.com/bvisible/mcp-ssh-manager/blob/main/CHANGELOG.md#385---2026-08-28