remote-ssh-mcp@0.3.0
CAUTION· install onlyPublisher claims: "Enables AI agents to run commands, read and write files, inspect containers and services, and check system health on remote Linux hosts configured in ~/.ssh/config, while blocking dangerous operations by default." Observed in sandbox: no network, touches nothing outside the project, writes no memory.
Coverage
Nothing executable in the bundle ran; the trace covers the install step only.- Tested
- every file read, file written and host contacted by what ran
- Not tested
- use of the skill by an agent
What this means for the label: Caution here covers what ran. The server's tools were not exercised with a real credential, so nothing about their behavior is asserted; the credential summary below says what to do with that.
Before you give it your token
- It will ask for
SSH_MCP_CF_TOKEN_DIRConfiguration, not credentials: CONTROL_PATH, SSH_MCP_ALLOW_PKG, SSH_MCP_ALLOW_POWER, SSH_MCP_HOST_SHELLS, SSH_MCP_TOOLS- Where it talks to
- no vendor host named in the codeAlso cloudflare.com — not the publisher's domain; check what for before connecting.
- What the honeypot saw
- no credential files read · no network
- What we could not test
- use of the skill by an agent
Connect it with a scoped credential, under the guard, and read the third-party hosts first. The code names cloudflare.com as well as its own vendor. The guard injects SSH_MCP_CF_TOKEN_DIR only into requests to the host you bind (and its subdomains) and refuses the rest.
Never paste a credential into a chat, a ticket or a report, including ours. How the guard holds it.
Is [email protected] safe to install?
KillerSkills ran it in the KillerSkills honeypot sandbox (1 scenario; nothing executable in the bundle ran; the trace covers the install step only) on 2026-11-13 and scored it 74/100 (Caution). It is not known to be malicious, but it has behaviour or code a security policy should decide on before install. Notable findings: Privileged sudo command; Privileged sudo command; Privileged sudo command. Summary: no network, touches nothing outside the project, writes no memory.
Behavior trace
Honeypot run · 0 s · 1 scenarios · 0 deviationsStatic findings
/** sudo 要的密码,只能配 sudo。 */Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.* 临时的 askpass 程序交给 sudo;askpass 只给一次密码,密码错了 sudo 不会接着试,免得连错几次锁住账号。Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.[ -e "$db" ] || { echo "x-ui.db not found (tried $dbs); pass sudo if they are not readable" >&2; exit 1; }Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.throw new Error(`未知主机「${host}」。请用 ~/.ssh/config 里的别名:${hosts.join(", ")}`);Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.* 已经是 root 时直接运行,主机没装 sudo 也不影响。Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell./** 带 pswd 时 askpass 从这个环境变量取密码;sudo 运行的命令里会去掉它。 */Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell./** 经 sudo 以 root 身份运行(见 sudoWrap)。 */Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.* 不带 pswd 时用 `sudo -n`,主机要密码就直接失败,并提示传 pswd。带 pswd 时,密码作为标准输入的第一行Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell./** 跳过变量赋值和 sudo 这类包装命令,取简单命令的命令名(按 baseName 处理)和参数。 */Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.if (o.sudo && o.posix === false) return "sudo 只支持 shell posix。";Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell."description": "按 ~/.ssh/config 里的主机别名在远程主机上执行常用运维命令的 MCP 服务",Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose./** Include 的相对路径按 ~/.ssh 解析;支持 `~`,路径最后一段支持 `*`、`?` 通配。 */Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.pswd: sudoArgs.pswd.describe("sudo 要的密码,一般是登录用户自己的;只试一次"),Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.* 让 `remoteCmd` 经 sudo 以 root 身份运行(`-H` 让家目录也换成 root 的),返回新的命令行和标准输入。Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.* `cmd` 里有命令把标准输入当脚本运行时为 true:不带 `-c` 的 shell(`sh`、`bash -s`、`sudo bash`),Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.sudo: sudoArgs.sudo.describe("以 root 身份运行,家目录也换成 root 的;sudo 要密码时再传 pswd"),Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.* 经 ssh 运行,不格式化结果;只有主机未知、sudo 和 pswd 组合不对或 conn 不对时才抛错。主机有 GNU `timeout` 时,Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell."sudo apt remove nginx",Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.["sudo -n reboot", "power"],Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.fakeSsh.envs.push(opts?.env);Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.chmod "$m" "$t"Fix: Request the narrowest permission that works; replace wildcards with the exact paths or hosts.chmod "$(printf '%o' $((0666 & ~$(umask))))" "$t"Fix: Request the narrowest permission that works; replace wildcards with the exact paths or hosts.it("timeout 包在 sudo 里面,退出码照样传回", () => {Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.expect(w.cmd).toMatch(/sudo -A -H -- env -u MCP_SUDO_PW .* 'sh -c '\\''exec timeout -k 5/);Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.["proxy http://user:[email protected]:8080", "proxy http://user:<redacted>@10.0.0.1:8080"],Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.const askpass = opts?.env?.SSH_ASKPASS;Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.// 真 sudo 运行命令前会清掉环境变量,这个不清,好检查命令里看不到密码变量。Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.chown "$o" "$t" 2>/dev/null || trueFix: Request the narrowest permission that works; replace wildcards with the exact paths or hosts.chmod 700 "$a/askpass"Fix: Request the narrowest permission that works; replace wildcards with the exact paths or hosts.it.each(["sh", "sh -s", "bash -s -- a b", "sudo bash", "cd /tmp && sh"])("shell 从标准输入读脚本:%s", (cmd) => {Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.it("命令收到的标准输入和不带 sudo 时相同", () => {Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.if (mode & 0o077) throw new Error(`令牌文件 ${file} 的权限是 ${mode.toString(8)},别人也能读;请先 chmod 600。`);Fix: Request the narrowest permission that works; replace wildcards with the exact paths or hosts.it("密码错时 askpass 只给一次,sudo 不再接着试", () => {Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.const kill = () => {Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell."sudo -u root /sbin/shutdown -h now",Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.expect(() => readToken(dir, "v")).toThrow(/权限是 644.*chmod 600/);Fix: Request the narrowest permission that works; replace wildcards with the exact paths or hosts."sudo reboot",Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.# copy owner, then mode: GNU and busybox take stat -c, macOS takes stat -f; chown after chmod would clear setuidFix: Request the narrowest permission that works; replace wildcards with the exact paths or hosts.it("权限不是 600 的拒绝,并提示 chmod 600", () => {Fix: Request the narrowest permission that works; replace wildcards with the exact paths or hosts.Cost to the agent
Tokens estimated at four characters each. Skills load their instruction text when triggered; the figure is what that costs.
Known vulnerabilities
Vulnerability advisories (OSV) cover npm and PyPI packages; this registry has no advisory database.
What would make this Verified
6 points to 80 · weights: behavior 45%, static 25%, prompt 15%, publisher 15%- Unclaimed publisher≈ +8 on the totalClaim arcdent: a verified publisher gets +50 on publisher trust. It is free and usually instant with GitHub sign-in.
- Privileged sudo command≈ +4 on the totalBuild commands from fixed arguments; do not interpolate untrusted strings into a shell.
- Access to sensitive file paths≈ +4 on the totalStop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.
- File permission modification command≈ +2 on the totalRequest the narrowest permission that works; replace wildcards with the exact paths or hosts.
- URL with embedded credentials≈ +2 on the totalStop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.
- Process kill command≈ +2 on the totalBuild commands from fixed arguments; do not interpolate untrusted strings into a shell.