Thanks to visit codestin.com
Credit goes to github.com

Skip to content

ssh_db_query (MySQL): backtick-quoted identifiers are shell-evaluated, corrupting queries (cross-DB joins return empty) + command-injection risk #44

Description

@technophile77

Summary

For MySQL, ssh_db_query builds the remote command by interpolating the raw SQL into a double-quoted shell string (mysql ... -e "${query}" ...). The remote shell therefore evaluates backticks `...` (command substitution) and $... before mysql ever sees the query. Any SQL that uses backtick-quoted identifiers — e.g. a hyphenated database name `my-db`.Table — is silently corrupted and returns empty/incorrect results with no error. The same construction also allows arbitrary shell command execution on the remote host.

Affected code

src/database-manager.jsbuildMySQLQueryCommand() (v3.5.0):

// json branch
command += ` -e "${query}" --batch --skip-column-names | awk '...'`;
// non-json branch
command += ` -e "${query}"`;

buildPostgreSQLQueryCommand (-c "${query}") and the Mongo --eval "${query}" builder share the same double-quoting.

Reproduction

Two databases on one server, app and other-db:

SELECT a.id, o.note
FROM app_table a
LEFT JOIN `other-db`.notes o ON a.ext = o.ext
WHERE a.id = 1;
  • Run via ssh_db_query (database app): returns [], even though a matching row exists.
  • Run the identical SQL via mysql directly (e.g. a single-quoted heredoc): returns the row.

Cause: inside -e "... \other-db`.notes ...", the remote shell executes `` other-db`` as a command (command substitution) and substitutes its (empty) output, so MySQL actually receives... LEFT JOIN .notes ...` — an invalid/different reference — yielding empty/incorrect results. Queries without backticks are unaffected, which hides the bug.

Impact

  • Correctness: any query needing backtick identifiers is silently wrong — hyphenated db/table names, cross-database joins, reserved-word columns. Empty/incorrect results with no error are dangerous for debugging and automation.
  • Security: the same double-quoting executes `...` / $(...) from the query string on the remote host. isSafeQuery() only filters SQL keywords, so a query such as SELECT `some command` or SELECT '$(id)' runs shell commands on the target server — i.e. the "SELECT-only" DB tool can execute arbitrary remote commands.

Suggested fix

Stop letting the shell parse the query:

  • Feed the SQL to mysql via stdin with a quoted heredoc delimiter (mysql ... <<'__SQL__'__SQL__), so backticks/$ are never shell-evaluated; or
  • single-quote the -e argument and escape embedded single quotes ('\'').
  • Apply the same to the PostgreSQL and MongoDB builders.
  • Optionally harden isSafeQuery() against shell metacharacters as defense-in-depth.

Version: mcp-ssh-manager 3.5.0.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions