Details
-
New Feature
-
Status: Open (View Workflow)
-
Major
-
Resolution: Unresolved
-
None
-
Q2/2026 Server Maintenance
Description
Subject: Mask password in SHOW CREATE SERVER output
Previously, SHOW CREATE SERVER displayed the password in plaintext,
which posed a security risk as users with FEDERATED ADMIN privilege
could see credentials for remote database connections.
This patch masks the password value as '********' in the output while
keeping the actual password stored in mysql.servers for functional
use.
This change encourages the security best practice of using SERVER
objects (instead of inline credentials in CREATE TABLE) for
Spider/Federated tables, as the password is now protected from
casual exposure.
File: sql/sql_show.cc
Location: mysql_show_create_server() function (lines 1530-1588)
This function generates the output for SHOW CREATE SERVER command. It builds a string like:
CREATE SERVER `srv` FOREIGN DATA WRAPPER mysql OPTIONS (host 'localhost', password 'xxx', ...);
|
Original Code (lines 1564-1575):
engine_option_value* option= server->option_list;
|
bool first= true;
|
while (option)
|
{
|
if (!first)
|
buffer.append(STRING_WITH_LEN(", "));
|
buffer.append(option->name);
|
buffer.append(STRING_WITH_LEN(" "));
|
append_unescaped(&buffer, option->value.str, option->value.length);
|
first= false;
|
option= option->next;
|
}
|
This loops through all server options (stored as a linked list) and outputs each one as name 'value'. The append_unescaped() function handles proper quoting/escaping of the value string.
Modified Code:
engine_option_value* option= server->option_list;
|
bool first= true;
|
static const LEX_CSTRING password_str= {STRING_WITH_LEN("password")};
|
while (option)
|
{
|
if (!first)
|
buffer.append(STRING_WITH_LEN(", "));
|
buffer.append(option->name);
|
buffer.append(STRING_WITH_LEN(" "));
|
if (option->name.streq(password_str))
|
buffer.append(STRING_WITH_LEN("'********'"));
|
else
|
append_unescaped(&buffer, option->value.str, option->value.length);
|
first= false;
|
option= option->next;
|
}
|
Changes Explained:
- static const LEX_CSTRING password_str=
{STRING_WITH_LEN("password")}
;
- Declares a constant string "password" for comparison
- LEX_CSTRING is MariaDB's length-prefixed string struct: {const char* str, size_t length}
- STRING_WITH_LEN("password") is a macro that expands to "password", 8 (string and its length)
- static avoids recreating it on each function call
- if (option->name.streq(password_str))
- option->name is of type engine_option_value::Name, which inherits from Lex_ident_ci (case-insensitive identifier)
- streq() performs case-insensitive comparison using my_charset_utf8mb3_general1400_as_ci
- This means PASSWORD, Password, password all match
- buffer.append(STRING_WITH_LEN("'********'"));
- If it's a password option, append the masked literal string
- Already includes quotes, so no need for append_unescaped()
- else append_unescaped(...)
- For all other options, use the original behavior
Data Structures Involved:
// From sql/create_options.h
|
class engine_option_value {
|
Name name; // Inherits from Lex_ident_ci (case-insensitive)
|
Value value; // The option value string
|
engine_option_value *next; // Linked list pointer
|
bool quoted_value; // Was value quoted in SQL?
|
...
|
};
|
|
// From sql/lex_ident.h
|
class Lex_ident_ci {
|
// Case-insensitive identifier comparison
|
bool streq(const LEX_CSTRING &rhs) const {
|
return my_charset_utf8mb3_general1400_as_ci.streq(*this, rhs);
|
}
|
};
|
Flow:
SHOW CREATE SERVER srv;
│
▼
mysql_show_create_server()
│
▼
Loop through server->option_list
│
├─► option->name == "host" → append "host 'localhost'"
├─► option->name == "password" → append "password '********'" ← MASKED
├─► option->name == "user" → append "user 'root'"
└─► option->name == "port" → append "port '3306'"
│
▼
Return: CREATE SERVER `srv` ... OPTIONS (host 'localhost', password '********', ...);
The actual password remains untouched in server->option_list and in mysql.servers table - only the display output is masked.
Attachments
Issue Links
- split to
-
MDEV-38601 SHOW CREATE SERVER does not require FEDERATED ADMIN
-
- Open
-