CVE-2026-7039 - ssh-mcp description command injection
tufantunc/ssh-mcp versions through 1.5.0 are reported vulnerable to command
injection in the MCP SSH execution path. The issue is especially dangerous when
su mode is enabled: the description metadata field can be appended to a
shell command and written to an interactive shell through shell.write().
The public report describes newline injection in description. A benign-looking
tool description can terminate the comment context and add a second command that
runs with the privileges of the active shell. In su mode, that can become root
command execution on the SSH target.
When to use it
Use this recipe when a repository, MCP catalog, or agent runtime uses
tufantunc/ssh-mcp to execute SSH commands or expose SSH tools to model-driven
callers. It is built for source-code remediation, shell-write hardening,
description-field sanitization, and audit evidence that metadata cannot become
commands on an SSH target.
Inputs
ssh-mcpversion, MCP config, SSH execution mode,sumode setting, enabled SSH tools, and deployment exposure.- Source paths that handle descriptions, construct shell input, call
shell.write(), entersu, or serialize command output/errors. - Regression fixtures for newline injection, comment termination, shell
metacharacters, harmless descriptions, disabled
su, and least-privilege command execution. - Runtime boundary evidence: target host scope, SSH credentials, user identity, shell privileges, logs, and who can submit tool descriptions.
Affected versions
- Vulnerable:
tufantunc/ssh-mcp <=1.5.0 - Fixed: no confirmed fixed release was identified in the checked GitHub
Advisory Database and issue sources. If a later release exists, treat it as
fixed only after verifying the changelog or patch removes newline/control
character injection before
shell.write().
Indicator-of-exposure
- The repository installs, vendors, builds, packages, or documents
tufantunc/ssh-mcp. - An MCP host can invoke the
execorsudo-exectools with a caller-supplieddescriptionfield. --suPassword, persistentsushell mode, privileged SSH users, or broad sudo permissions are enabled.- LLM-generated tool calls or user-controlled prompts can influence the
descriptionvalue. - MCP logs show descriptions with line breaks, carriage returns, shell metacharacters, or unexpected commands near SSH execution events.
Quick checks:
rg -n "ssh-mcp|tufantunc|suPassword|sudo-exec|shell.write|description" .
npm ls ssh-mcp
pnpm why ssh-mcp
yarn why ssh-mcp
rg -n "mcp.*ssh|ssh.*mcp|tools/call|description" .mcp* config* docker-compose*.yml Dockerfile* charts deploy
Remediation strategy
- Remove or disable
ssh-mcpwhere it is not strictly required. - Do not run affected
ssh-mcpversions with--suPassword, persistent root shells, privileged SSH users, or broad sudo access. - If this repository owns a fork or vendored copy, patch command construction so
human-readable descriptions are never concatenated into executable shell
input. At minimum, reject or normalize
\n,\r, NUL, ANSI control characters, and shell command delimiters before anyshell.write()call. - Prefer structured logging for descriptions instead of appending them as shell comments.
- Run the MCP server with a dedicated least-privilege SSH identity, explicit command allow-lists, session recording, and egress/host restrictions.
- Rotate SSH credentials and review command logs if an exposed deployment ran affected versions with privileged shell mode.
The prompt
You are remediating CVE-2026-7039 (tufantunc ssh-mcp description command
injection). Produce exactly one output:
- A reviewer-ready PR/change request that removes, upgrades, or safely patches
the affected MCP SSH execution path and documents operator cleanup, or
- TRIAGE.md if this repository does not own an affected deployment or cannot
make a safe patch.
## Rules
- Scope only CVE-2026-7039.
- Treat SSH private keys, passwords, sudo passwords, MCP tokens, command output,
session transcripts, and hostnames as sensitive. Do not print or commit them.
- Do not run exploit payloads against production, staging, shared SSH targets,
developer machines, or real privileged accounts.
- Do not preserve `su` shell behavior by only escaping one character class.
- Do not auto-merge.
## Steps
1. Inventory every `ssh-mcp` reference controlled by this repository:
`package.json`, lockfiles, vendored source, Dockerfiles, compose files,
Helm values, Kubernetes manifests, MCP client/server config, runbooks, CI,
generated SBOMs, and deployment docs.
2. Determine whether any deployable target runs `tufantunc/ssh-mcp <=1.5.0`.
3. Determine whether the dangerous path is reachable:
- `exec` or `sudo-exec` MCP tools are enabled;
- tool callers can supply `description`;
- `--suPassword` or persistent `su` shell mode is enabled;
- the SSH identity has root, passwordless sudo, or broad host access;
- an LLM, user prompt, ticket body, workflow input, or remote config can
influence tool arguments.
4. If the package is not present or the repository only contains unrelated
docs, stop with `TRIAGE.md` listing the files checked and the owner that
must remediate the runtime.
5. Prefer removal or disablement when SSH command execution is not required.
Remove the MCP server registration, image, dependency, and runbook steps.
6. If a verified fixed upstream release is available, upgrade to that release,
regenerate lockfiles/SBOMs/images, and keep the hardening steps below.
7. If this repository owns a fork or vendored code, patch command handling:
- keep `description` out of executable shell input entirely;
- log description as structured metadata, not a shell comment;
- reject or normalize `\n`, `\r`, NUL, ANSI controls, backticks, `$()`,
semicolons, pipes, redirects, and other shell delimiters before any legacy
compatibility path;
- add a single command-construction helper used by `exec`, `sudo-exec`, and
any shared SSH execution path;
- ensure the value passed to `shell.write()` is built from validated command
fields only.
8. Add safe tests that do not contact a real SSH host:
- a unit test proving descriptions containing `\n id`, `\r`, `;`, `&&`,
backticks, and `$()` are rejected or logged as inert metadata;
- a test proving the command sent to the shell excludes description text;
- a regression test covering both normal and `su`/sudo execution builders.
9. Add deployment containment where this repo controls it:
- disable `--suPassword` and persistent root shell mode by default;
- run with a dedicated low-privilege SSH account;
- restrict allowed commands or target hosts;
- add audit logging that records command IDs without secrets.
10. Add a PR body section named `CVE-2026-7039 operator actions` that states:
- whether `ssh-mcp` was removed, upgraded, or patched;
- whether `su` mode or privileged SSH identities were present;
- which MCP clients or workflows could supply `description`;
- which SSH keys, passwords, or host credentials should be rotated;
- which MCP and SSH logs should be reviewed for multiline descriptions or
unexpected child commands.
11. Run relevant validation: package install, lockfile integrity, unit tests,
lint/typecheck, container build, MCP config validation, SBOM generation, and
dependency/security scans available in this repository.
12. Use PR title:
`fix(sec): remediate CVE-2026-7039 in ssh-mcp`.
## Stop conditions
- No `ssh-mcp` deployment, package, vendored source, or MCP registration is
controlled by this repository.
- A verified fixed upstream release is unavailable and the repository does not
own a fork or vendored patch path.
- The only apparent fix would require running exploit commands against real SSH
hosts.
- The product intentionally requires root shell MCP access and there is no
approved decision to remove or contain it.
- Validation fails for unrelated pre-existing reasons; document those failures
instead of broadening scope.
Output contract
- A reviewer-ready PR or change request that removes or contains affected
ssh-mcpversions, patches newline/description handling, adds shell-write regression tests, and documents credential cleanup. - Or a
TRIAGE.mdfile that lists inspected files, owner, observed version, SSH privilege boundary, exposed tools, required fix, and residual risk. - The output must include exact validation commands and must not run exploit payloads, mutate SSH targets, print credentials, or use production hosts.
Verification - what the reviewer looks for
- No controlled deployment still runs
tufantunc/ssh-mcp <=1.5.0withsumode enabled unless there is a documented operator-owned containment decision. - Descriptions are never concatenated into the string sent to
shell.write(). - Regression tests prove multiline/control-character descriptions cannot add a command.
- MCP configuration removes or restricts privileged SSH execution paths.
- Operator actions cover credential rotation and review of MCP/SSH command logs for the exposure window.
Watch for
- Treating
descriptionas harmless metadata even though tool arguments can be shaped by users or LLM output. - Escaping only
#or only newlines while leaving other shell delimiters active. - Updating package manifests while old MCP server registrations, images, or global installs remain in use.
- Running the MCP server with developer SSH keys or root-capable automation credentials.
Related recipes
- Source code injection sink audit
- Source code secrets and data exposure audit
- Source code attack surface map
- SAST finding triage and fix
References
- GitHub Advisory Database listing: https://github.com/advisories?query=severity%3Ahigh+sort%3Apublished-desc
- NVD: https://nvd.nist.gov/vuln/detail/CVE-2026-7039
- CVE record: https://www.cve.org/CVERecord?id=CVE-2026-7039
- Public issue report: https://github.com/tufantunc/ssh-mcp/issues/44
- VulDB advisory: https://vuldb.com/vuln/359619