You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
PROXYSQL40: a plugin can register an admin command that shadows a core command (e.g. LOAD MYSQL SERVERS TO RUNTIME) #6459
On PROXYSQL40 builds, a loaded plugin can register an admin command, or an alias, whose spelling matches a core admin command. Plugin commands are dispatched before the core LOAD/SAVE handler, so the plugin callback replaces the core operation and its reply. If the callback fails, Admin returns Plugin failed to handle registered command instead of running the core command.
This violates invariant I-3 in doc/agents/invariants.md (#6458): plugins must not be able to make core admin commands fail, block them, or change their reply. The architecture review listed it as ADM-14 ("no reservation of core command names").
No in-tree plugin does this today (genai, mysqlx, mysql_router, duckdb). The gap is in the chassis: nothing prevents it. v3.0/v3.1 are not affected, because the dispatch branch compiles out.
lib/Admin_Handler.cpp:~4006-4034 (#ifdef PROXYSQL40): proxysql_resolve_configured_plugin_admin_alias() runs on every admin query that reaches this point. On a match it calls dispatch_plugin_admin_command() and returns.
lib/Admin_Handler.cpp:~4038: admin_handler_command_load_or_save() runs only afterwards.
lib/ProxySQL_PluginManager.cppregister_command() (~2179) and register_command_alias() canonicalize the SQL (canonicalize_plugin_command: trim, collapse whitespace, strip ;). They reject only duplicates among plugin commands, and never check core command spellings.
resolve_alias_to_canonical() (~1280) matches case-insensitively on the canonical form or any alias.
So a plugin calling register_command("LOAD MYSQL SERVERS TO RUNTIME", cb) or register_command_alias(<own cmd>, "load mysql servers to run") captures that core command.
Expected
register_command and register_command_alias reject any canonical form that matches a core admin command or one of its aliases, after the same normalization dispatch uses. The rejection is logged with the plugin name.
Admin never dispatches a core command spelling to a plugin.
The reserved list comes from the same tables core dispatch uses (for example the LOAD_*/SAVE_* command/alias vectors in Admin_Handler.cpp used by is_admin_command_or_alias). It is not a second hand-maintained copy, which would drift.
Tests
Unit (test/tap/tests/unit/, against the real ProxySQL_PluginManager):
registering a core spelling fails, including a different case or whitespace variant and an abbreviated alias such as ... TO RUN;
registering a core spelling as an alias fails;
a genuine plugin command still registers.
Optional TAP check on a PROXYSQL40 build: with a fake plugin that attempts the registration, LOAD MYSQL SERVERS TO RUNTIME still runs the core handler.
Activity