Skip to content

v3.8.5 — Security: three command-injection advisories, one bypassing readonly mode

Latest

Choose a tag to compare

@bvisible bvisible released this 28 Aug 14:07
· 1 commit to main since this release

🔴 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 to src/shell-quote.js and imported by every builder, so "did this quote its inputs?" has one answer instead of one per file. Applied across backup-manager.js (54 call sites), health-monitor.js, and the remaining inline commands in index.js.
  • safeInteger() for numeric arguments that still land in command strings.
  • buildProcessInfoCommand validates its PID, as buildKillProcessCommand always did.
  • ssh_tail and ssh_service_status now 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