Skip to content

fix(auth): allow mysql-monitor_* to authenticate under caching_sha2_password - #5991

Merged
renecannao merged 2 commits into
v3.0from
fix/5363-monitor-caching-sha2
Aug 9, 2026
Merged

fix(auth): allow mysql-monitor_* to authenticate under caching_sha2_password#5991
renecannao merged 2 commits into
v3.0from
fix/5363-monitor-caching-sha2

Conversation

@renecannao

@renecannao renecannao commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Fixes #5363. Implements #5986.

Problem

mysql-monitor_username / mysql-monitor_password cannot authenticate on the Admin interface (:6032) when mysql-default_authentication_plugin = 'caching_sha2_password'. It works under mysql_native_password. TLS does not help. This is what breaks k8s liveness/readiness probes and metrics exporters.

That credential is not in GloMyAuth, so PPHR_verify_password() reaches it via its vars1.password == NULL branch and PPHR_5passwordFalse_0() (MySQL_Protocol.cpp) is the only code that authenticates it. It was hardcoded to the native SHA1 scramble with a 20-byte compare; under caching_sha2 the client sends a 32-byte SHA256-derived response, so it could never match. It returned false without ever sending perform full authentication, which is why the transport was irrelevant.

The pre-existing // FIXME: does this work only for mysql_native_password ? on the line above was this bug.

Fix

Dispatch on auth_plugin_id. The caching_sha2 fast-auth verification already existed in PPHR_6auth2(); it's extracted into caching_sha2_fast_auth_verify() so there is exactly one implementation, with PPHR_6auth2() now calling it. Successful caching_sha2 fast auth also emits the fast_auth_success (0x03) marker before the OK packet, mirroring the PPHR_6auth2() call site.

Also: a 1-byte 0x02 at switching_auth_stage == 5 is the caching_sha2 request_public_key packet, not a disconnect. It was logged as "client is disconnecting during switch auth", which sends operators to the wrong place. The log line now names the real cause. Client-visible messaging needs the session-level error path and is left to #5988.

Deliberately not length-gated — please keep it that way

Both comparisons carry a comment explaining this, because it is genuinely counter-intuitive:

vars1.pass_len is not the amount of valid data in vars1.pass. PPHR_2 (MySQL_Protocol.cpp:1884) strips a trailing NUL — "remove the extra 0 if present" — so a legitimate 32-byte caching_sha2 response whose last byte is 0x00 (p = 1/256) arrives with pass_len == 31 while all 32 bytes are present in the buffer.

An earlier revision of this branch gated on pass_len and caused intermittent Access denied on the frontend. Measured with an instrumented build: 20 spurious denials across ~6520 connections (0.31%, predicted 0.39%), every one reporting client_response_len=31. The same mistake was also present in the monitor's native branch, where it would have intermittently broken the very credential this PR fixes. Both are removed; PPHR_6auth2() is behaviourally identical to v3.0.

There is a real out-of-bounds read here for a deliberately short response (allocation is malloc(N_original+1), so a client declaring pass_len=1 gets a 2-byte buffer against a 32-byte memcmp). That is pre-existing, not introduced or worsened by this PR, and is being filed separately — a length guard on this comparison needs its own verification run, which is exactly the lesson above.

Verification

check result
test/repro/reg_test_5363_admin_monitor_caching_sha2.bash exit 1 → exit 0, 10/10 on a cold instance
new reg_test_5363_admin_monitor_caching_sha2-t 12/12
same test with the fix reverted and rebuilt fails exactly assertions 7 and 8 with errno 1045
test_auth_methods-t (40194 assertions) PASS
reg_test_4935-caching_sha2-t PASS
full no-infra-g1 group PASS

The revert check matters: a regression test that doesn't fail on the bug is worthless, so it was verified against a rebuilt pre-fix binary rather than assumed.

How the TAP test asserts this in CI

The monitor credential has a locality restriction, so an off-box connection is refused even with the right password — which is what makes it testable without running a client inside the container:

  • 1040 "can only connect locally" → authentication succeeded, rejected afterwards
  • 1045 "Access denied" → authentication failed

The regression is precisely "correct password yields 1045 instead of 1040 under caching_sha2". The repro script does connect locally and asserts a real login; the two are complementary.

Also lands: test/repro/

Two developer-facing reproductions plus a README. Not CI artifacts — the TAP tests are. Teardown is opt-in (COLD_START=1, destructive), both scripts refuse to run against a release build, and both abort if the running container predates src/proxysql so a rebuilt fix can't silently go untested. Exit codes separate "bug reproduced" (1) from "environment wrong" (2).

Note for the reviewer

reg_test_5363_admin_monitor_caching_sha2-t is registered in no-infra-g1, alongside test_passthrough_auth_admin-t, since it needs ProxySQL but no backend. I could not find any workflow referencing that group — grep -rn "no-infra" .github/workflows/ returns nothing on this branch. If there's no ci-no-infra-g1 caller on GH-Actions, this test (and the four already in the group) never run in CI, and it should move or the group should be wired up.

Summary by CodeRabbit

  • Bug Fixes

    • Corrected RSA public-key request authentication logging to ensure session details are recorded accurately.
    • Improved Admin authentication handling for caching_sha2_password, including monitor and full-authentication scenarios over secure connections.
  • Tests

    • Added regression coverage for successful and failed authentication, credential caching, TLS connections, and configuration restoration.
  • Documentation

    • Added guidance for reproducing and validating authentication-related issues, including setup requirements and cleanup procedures.

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7a65557a-6e0c-4937-9f5f-981fac2bb20a

📥 Commits

Reviewing files that changed from the base of the PR and between 9421d44 and d768c6e.

📒 Files selected for processing (1)
  • lib/MySQL_Protocol.cpp
📜 Recent review details
⏰ Context from checks skipped due to timeout. (5)
  • GitHub Check: CI-builds / builds (ubuntu22,-tap)
  • GitHub Check: CI-builds / builds (debian12,-dbg)
  • GitHub Check: CI-builds / builds (ubuntu22,-tap-mysqlx)
  • GitHub Check: run / trigger
  • GitHub Check: build
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{cpp,h,hpp}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{cpp,h,hpp}: Class names must use PascalCase with protocol prefixes such as MySQL_, PgSQL_, and ProxySQL_.
Member variables must use snake_case.
Constants and macros must use UPPER_SNAKE_CASE.
Use C++17, and gate conditional code with #ifdef PROXYSQL31, #ifdef PROXYSQL40, #ifdef PROXYSQLFFTO, #ifdef PROXYSQLTSDB, and #ifdef PROXYSQLCLICKHOUSE; PROXYSQLGENAI must not guard core code outside plugins/genai/.
Consider performance implications when changing hot paths or other performance-critical code.
Use RAII for resource management and jemalloc for allocation.
Use pthread mutexes for synchronization and std::atomic<> for counters.

Files:

  • lib/MySQL_Protocol.cpp
🔇 Additional comments (1)
lib/MySQL_Protocol.cpp (1)

1241-1241: LGTM!

Also applies to: 1262-1262, 1331-1331, 1349-1349, 1463-1463, 1712-1712, 2259-2261, 2362-2362, 2403-2403, 3220-3220


📝 Walkthrough

Walkthrough

The change corrects a caching-SHA2 RSA authentication log call and adds Bash, TAP, and documentation coverage for Admin monitor and full authentication scenarios.

Changes

Authentication regressions

Layer / File(s) Summary
Protocol authentication handling
lib/MySQL_Protocol.cpp
The RSA public-key request debug log receives the session and data-stream arguments in the corrected order.
Monitor authentication reproduction
test/repro/README.md, test/repro/reg_test_5363_admin_monitor_caching_sha2.bash
The reproduction script validates native and caching-SHA2 monitor authentication over plaintext and TLS, checks controls, restores variables, and reports distinct result codes.
Full authentication reproduction
test/repro/reg_test_5985_admin_caching_sha2_full_auth.bash
The script validates cold-cache caching-SHA2 authentication through the TLS Admin interface, invalid-password handling, cache counters, and state restoration.
TAP monitor regression
test/tap/tests/reg_test_5363_admin_monitor_caching_sha2-t.cpp
The TAP test covers valid and invalid monitor passwords across authentication plugins and connection modes, and verifies exact variable restoration.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related issues

Possibly related PRs

  • sysown/proxysql#5990 — Adds overlapping caching_sha2_password salt generation and Admin authentication round-trip coverage.
  • sysown/proxysql#5993 — Modifies related protocol authentication handling and Admin regression coverage.
  • sysown/proxysql#5956 — Provides related TLS Admin implementation and test coverage.

Poem

A rabbit checks each login path,
Through TLS and caches, clear and fast.
The SHA-2 keys now log just right,
Old state returns before twilight.
TAP hops cleanly; bugs stand in sight.

🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (3 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The only production change corrects logging argument order and does not implement the monitor authentication required by [#5363]. Add plugin-specific monitor authentication handling and fast-auth success signaling, then verify mysql-monitor credentials under caching_sha2_password.
Out of Scope Changes check ⚠️ Warning The #5985 full-auth reproduction and related documentation target an unlinked issue outside [#5363]'s monitoring-authentication scope. Move #5985-specific scripts and documentation to a separate pull request, or link an issue that explicitly requires this coverage.
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the primary authentication fix for mysql-monitor credentials under caching_sha2_password.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/5363-monitor-caching-sha2

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/MySQL_Protocol.cpp`:
- Around line 1710-1712: In the RSA public-key diagnostic’s proxy_debug call,
swap the first two pointer arguments so the Session label receives (*myds)->sess
and the DS label receives (*myds). Keep the message and remaining arguments
unchanged.

In `@test/repro/README.md`:
- Around line 39-42: Update the fenced block in README.md that documents
COLD_START values to specify the text language, preserving its existing content
and formatting.

In `@test/repro/reg_test_5363_admin_monitor_caching_sha2.bash`:
- Around line 146-150: The regression tests must preserve and restore the exact
authentication state. In
test/repro/reg_test_5363_admin_monitor_caching_sha2.bash lines 146-150, update
restore() and its setup to save and restore the original plugin,
mysql-monitor_username, and mysql-monitor_password values, and remove the
admin-admin_credentials reset. In
test/tap/tests/reg_test_5363_admin_monitor_caching_sha2-t.cpp lines 158-175,
save mysql-monitor_username alongside the existing saved values; in lines
198-220, restore that username and preserve an originally empty password instead
of substituting "monitor".

In `@test/repro/reg_test_5985_admin_caching_sha2_full_auth.bash`:
- Around line 138-144: Update the test setup around restore() to capture the
existing values of admin-admin_credentials and
mysql-default_authentication_plugin before modifying them, including when
COLD_START=0. Make restore() use those saved values in its UPDATE statements
before reloading both variable groups, rather than hard-coded defaults.

In `@test/tap/tests/reg_test_5363_admin_monitor_caching_sha2-t.cpp`:
- Around line 110-116: Update set_var to escape value before building the UPDATE
query’s quoted SQL literal, using the existing MySQL escaping utility or
established test helper. Preserve the current variable-name and load_stmt
behavior while ensuring quote and escape characters in value produce a valid SQL
query.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 6fe061c8-fcdd-448d-8c85-40e7d2f583e5

📥 Commits

Reviewing files that changed from the base of the PR and between 89a29ec and ca03c8d.

📒 Files selected for processing (6)
  • lib/MySQL_Protocol.cpp
  • test/repro/README.md
  • test/repro/reg_test_5363_admin_monitor_caching_sha2.bash
  • test/repro/reg_test_5985_admin_caching_sha2_full_auth.bash
  • test/tap/groups/groups.json
  • test/tap/tests/reg_test_5363_admin_monitor_caching_sha2-t.cpp
📜 Review details
🧰 Additional context used
📓 Path-based instructions (2)
test/tap/tests/**/*.cpp

📄 CodeRabbit inference engine (CLAUDE.md)

test/tap/tests/**/*.cpp: Test files in test/tap/tests/ must follow the naming pattern test_*.cpp or *-t.cpp.
To add a new TAP test, add the <testname>-t.cpp file and register it in test/tap/tests/Makefile/groups.json; no special Makefile target is needed because make <testname>-t is generated by pattern rule.

Files:

  • test/tap/tests/reg_test_5363_admin_monitor_caching_sha2-t.cpp
**/*.{cpp,h,hpp}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{cpp,h,hpp}: Class names must use PascalCase with protocol prefixes such as MySQL_, PgSQL_, and ProxySQL_.
Member variables must use snake_case.
Constants and macros must use UPPER_SNAKE_CASE.
Use C++17, and gate conditional code with #ifdef PROXYSQL31, #ifdef PROXYSQL40, #ifdef PROXYSQLFFTO, #ifdef PROXYSQLTSDB, and #ifdef PROXYSQLCLICKHOUSE; PROXYSQLGENAI must not guard core code outside plugins/genai/.
Consider performance implications when changing hot paths or other performance-critical code.
Use RAII for resource management and jemalloc for allocation.
Use pthread mutexes for synchronization and std::atomic<> for counters.

Files:

  • test/tap/tests/reg_test_5363_admin_monitor_caching_sha2-t.cpp
  • lib/MySQL_Protocol.cpp
🧠 Learnings (3)
📚 Learning: 2026-04-11T13:17:55.508Z
Learnt from: renecannao
Repo: sysown/proxysql PR: 5607
File: doc/GH-Actions/README.md:13-18
Timestamp: 2026-04-11T13:17:55.508Z
Learning: When using GitHub-flavored Markdown headings, be aware that an em-dash surrounded by spaces (written as ` — `) affects the generated anchor/slug: GitHub replaces spaces with hyphens and removes non-alphanumeric punctuation, which can produce double hyphens (e.g., `## Foo — bar` → anchor `#foo--bar`, not `#foo-bar`). If you reference these anchors (e.g., internal links), ensure the expected slug matches this behavior.

Applied to files:

  • test/repro/README.md
📚 Learning: 2026-04-11T13:17:55.509Z
Learnt from: renecannao
Repo: sysown/proxysql PR: 5607
File: doc/GH-Actions/README.md:13-18
Timestamp: 2026-04-11T13:17:55.509Z
Learning: When reviewing GitHub-flavored Markdown links/anchors, remember that heading-to-anchor slug generation treats spaces as hyphens and removes punctuation. If a heading contains an em-dash surrounded by spaces (e.g. ` — `), the slugs can legitimately include a double hyphen where the two surrounding space-runs become `-` on either side of the removed em-dash (e.g. `...vocabulary--read...`). Do not flag double-hyphens in anchor links for em-dash-containing headings as errors; they reflect GitHub’s correct slug behavior.

Applied to files:

  • test/repro/README.md
📚 Learning: 2026-01-20T09:34:19.124Z
Learnt from: yuji-hatakeyama
Repo: sysown/proxysql PR: 5307
File: test/tap/tests/reg_test_5306-show_warnings_with_comment-t.cpp:39-48
Timestamp: 2026-01-20T09:34:19.124Z
Learning: In ProxySQL's TAP test suite, resource leaks (e.g., not calling mysql_close() on early return paths) are commonly tolerated because test processes are short-lived and OS frees resources on exit. This pattern applies to all C++ test files under test/tap/tests. When reviewing, recognize this as a project-wide test convention and focus on test correctness and isolation rather than insisting on fixing such leaks in these test files.

Applied to files:

  • test/tap/tests/reg_test_5363_admin_monitor_caching_sha2-t.cpp
🪛 Cppcheck (2.21.0)
lib/MySQL_Protocol.cpp

[warning] 2328-2328: Uninitialized variable

(uninitvar)

🪛 markdownlint-cli2 (0.23.2)
test/repro/README.md

[warning] 39-39: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🪛 Shellcheck (0.11.0)
test/repro/reg_test_5985_admin_caching_sha2_full_auth.bash

[warning] 92-92: This assignment is only seen by the forked process.

(SC2097)


[warning] 93-93: This expansion will not see the mentioned assignment.

(SC2098)


[warning] 98-98: This assignment is only seen by the forked process.

(SC2097)


[warning] 99-99: This expansion will not see the mentioned assignment.

(SC2098)


[warning] 103-103: This assignment is only seen by the forked process.

(SC2097)


[warning] 104-104: This expansion will not see the mentioned assignment.

(SC2098)


[info] 138-143: This function is never invoked. Check usage (or ignored if invoked indirectly).

(SC2329)


[info] 148-148: Note that A && B || C is not if-then-else. C may run when A is true.

(SC2015)


[info] 151-151: Note that A && B || C is not if-then-else. C may run when A is true.

(SC2015)


[info] 164-164: Note that A && B || C is not if-then-else. C may run when A is true.

(SC2015)


[info] 193-193: Note that A && B || C is not if-then-else. C may run when A is true.

(SC2015)


[info] 197-197: Note that A && B || C is not if-then-else. C may run when A is true.

(SC2015)


[info] 203-203: Note that A && B || C is not if-then-else. C may run when A is true.

(SC2015)


[info] 208-208: Note that A && B || C is not if-then-else. C may run when A is true.

(SC2015)


[info] 213-213: Note that A && B || C is not if-then-else. C may run when A is true.

(SC2015)


[info] 217-217: Note that A && B || C is not if-then-else. C may run when A is true.

(SC2015)


[info] 221-221: Note that A && B || C is not if-then-else. C may run when A is true.

(SC2015)

test/repro/reg_test_5363_admin_monitor_caching_sha2.bash

[warning] 109-109: This assignment is only seen by the forked process.

(SC2097)


[warning] 110-110: This expansion will not see the mentioned assignment.

(SC2098)


[warning] 113-113: This assignment is only seen by the forked process.

(SC2097)


[warning] 114-114: This expansion will not see the mentioned assignment.

(SC2098)


[warning] 118-118: This assignment is only seen by the forked process.

(SC2097)


[warning] 119-119: This expansion will not see the mentioned assignment.

(SC2098)


[info] 146-150: This function is never invoked. Check usage (or ignored if invoked indirectly).

(SC2329)


[info] 156-156: Note that A && B || C is not if-then-else. C may run when A is true.

(SC2015)


[info] 159-159: Note that A && B || C is not if-then-else. C may run when A is true.

(SC2015)


[info] 166-166: Note that A && B || C is not if-then-else. C may run when A is true.

(SC2015)


[info] 173-173: Note that A && B || C is not if-then-else. C may run when A is true.

(SC2015)


[info] 176-176: Note that A && B || C is not if-then-else. C may run when A is true.

(SC2015)


[info] 183-183: Note that A && B || C is not if-then-else. C may run when A is true.

(SC2015)


[info] 187-187: Note that A && B || C is not if-then-else. C may run when A is true.

(SC2015)


[info] 190-190: Note that A && B || C is not if-then-else. C may run when A is true.

(SC2015)


[info] 198-198: Note that A && B || C is not if-then-else. C may run when A is true.

(SC2015)


[info] 201-201: Note that A && B || C is not if-then-else. C may run when A is true.

(SC2015)

🔇 Additional comments (3)
test/tap/groups/groups.json (1)

276-276: LGTM!

lib/MySQL_Protocol.cpp (1)

2075-2180: LGTM!

Also applies to: 2280-2341

test/repro/reg_test_5985_admin_caching_sha2_full_auth.bash (1)

1-136: LGTM!

Also applies to: 146-242

Comment thread lib/MySQL_Protocol.cpp Outdated
Comment thread test/repro/README.md Outdated
Comment thread test/repro/reg_test_5363_admin_monitor_caching_sha2.bash
Comment thread test/repro/reg_test_5985_admin_caching_sha2_full_auth.bash
Comment on lines +110 to +116
static int set_var(MYSQL* admin, const char* name, const char* value, const char* load_stmt) {
const string q {
string("UPDATE global_variables SET variable_value='") + value +
"' WHERE variable_name='" + name + "'"
};
MYSQL_QUERY_T(admin, q.c_str());
MYSQL_QUERY_T(admin, load_stmt);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Escape value before constructing the SQL literal.

Line 112 inserts value directly into a quoted SQL literal. An existing mysql-monitor_password can contain a quote or escape character. The restore query can then fail and leave shared authentication state modified.

Use a correctly escaped SQL literal for value.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/tap/tests/reg_test_5363_admin_monitor_caching_sha2-t.cpp` around lines
110 - 116, Update set_var to escape value before building the UPDATE query’s
quoted SQL literal, using the existing MySQL escaping utility or established
test helper. Preserve the current variable-name and load_stmt behavior while
ensuring quote and escape characters in value produce a valid SQL query.

@codecov

codecov Bot commented Aug 7, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 52.38%. Comparing base (90d4cc1) to head (d768c6e).

Additional details and impacted files
@@            Coverage Diff             @@
##             v3.0    #5991      +/-   ##
==========================================
- Coverage   52.41%   52.38%   -0.04%     
==========================================
  Files         472      472              
  Lines      143270   143270              
  Branches    36196    36196              
==========================================
- Hits        75102    75052      -50     
- Misses      51322    51331       +9     
- Partials    16846    16887      +41     
Flag Coverage Δ
integration-tests 48.83% <ø> (-0.04%) ⬇️
unit-tests 13.87% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

…pros

Addresses the CodeRabbit review on #5991.

The repro scripts and the TAP test run against a SHARED instance, and
test/repro/README.md already requires that they "restore any global state that
was changed". They did not:

  - reg_test_5363_*.bash reset 'admin-admin_credentials' to a hardcoded
    BASE_CREDS even though it never modifies that variable, reset the
    authentication plugin and monitor password to hardcoded defaults, and never
    restored 'mysql-monitor_username' at all -- which it does mutate.
  - reg_test_5985_*.bash reset 'admin-admin_credentials' and the authentication
    plugin to hardcoded values, discarding whatever the instance had.
  - reg_test_5363_*-t.cpp never saved 'mysql-monitor_username', and substituted
    "monitor" / "mysql_native_password" whenever the saved value was empty,
    overwriting a legitimately empty value with a guess.

All three now capture the actual values up front and restore exactly those. The
TAP test distinguishes "read an empty value" from "could not read" via a new
read_var() helper, and leaves an unreadable variable alone rather than guessing.
The 5985 retry loop now rebuilds on the instance's real credential list instead
of a hardcoded one.

Verified by A/B against a seeded non-default state (an extra 'canary:canarypw'
admin credential plus non-default monitor username/password):
  - committed version: canary credential destroyed, both monitor variables reset
  - this version:      all three preserved byte-for-byte
reg_test_5363_admin_monitor_caching_sha2-t passes 13/13, including the new
"mysql-monitor_username restored" assertion (plan updated 12 -> 13).

Also from the same review:
  - swap the Session/DS arguments in the RSA public-key proxy_debug
  - give the COLD_START fenced block in test/repro/README.md a language (MD040)

Sonar (65 new issues on this PR, 64 of them in these two new scripts): use [[
over [, assign positional parameters to locals, add explicit returns, and hoist
the repeated LOAD MYSQL VARIABLES literal into a constant. shellcheck -S warning
is now clean on both scripts (the env-prefix SC2097/SC2098 pairs are gone: the
three variables are exported once instead).

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (1)
test/tap/tests/reg_test_5363_admin_monitor_caching_sha2-t.cpp (1)

127-138: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Use RAII for MYSQL_RES.

Automate mysql_free_result() with a std::unique_ptr deleter so this query result cannot be skipped by future control-flow changes.

Proposed change
+#include <memory>
+
-	MYSQL_RES* r = mysql_store_result(admin);
-	if (r == NULL) { return false; }
-	MYSQL_ROW row = mysql_fetch_row(r);
+	std::unique_ptr<MYSQL_RES, decltype(&mysql_free_result)> r(
+		mysql_store_result(admin), mysql_free_result);
+	if (!r) { return false; }
+	MYSQL_ROW row = mysql_fetch_row(r.get());
 	const bool found = (row != NULL && row[0] != NULL);
 	if (found) { out = row[0]; }
-	mysql_free_result(r);
 	return found;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/tap/tests/reg_test_5363_admin_monitor_caching_sha2-t.cpp` around lines
127 - 138, Update read_var to wrap the MYSQL_RES returned by mysql_store_result
in a std::unique_ptr with a mysql_free_result deleter, replacing the manual
cleanup while preserving the existing found check and output assignment.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/repro/reg_test_5363_admin_monitor_caching_sha2.bash`:
- Line 69: Preserve the caller-provided COLD_START value instead of
unconditionally assigning “-e” near the script’s initialization. Update the
cold-start branching logic around COLD_START and its usage message so the branch
remains reachable when the caller requests a cold start and the displayed
invocation matches the actual accepted value.
- Around line 91-94: Update the setvar() helper to SQL-escape or otherwise
safely serialize both value and name before interpolating them into the UPDATE
statement, preserving exact restoration of values containing quotes or
backslashes; ensure the same encoding is used for all calls that restore
ORIG_MON_USER and ORIG_MON_PASS.

In `@test/repro/reg_test_5985_admin_caching_sha2_full_auth.bash`:
- Line 57: Preserve any caller-provided COLD_START value instead of
unconditionally assigning "-e" in the test setup. Update the related logic
around the condition at line 100 so COLD_START=1 still triggers instance
recreation and the cold-cache test runs, while retaining the existing default
behavior when no value is supplied.
- Around line 151-158: Make the configuration snapshot and restore flow
lossless: require both adm reads for ORIG_ADMIN_CREDS and ORIG_AUTH_PLUGIN to
succeed before modifying any state, and capture each value as HEX. Update
restore() and the later admin-admin_credentials reconstruction to restore and
reuse values through UNHEX, escaping no raw quoted data, and calculate
EXPECT_LEN from the original byte length rather than the encoded representation.

In `@test/tap/tests/reg_test_5363_admin_monitor_caching_sha2-t.cpp`:
- Around line 190-193: The diagnostic at
test/tap/tests/reg_test_5363_admin_monitor_caching_sha2-t.cpp:190-193 must not
output the monitor password; replace its value with a fixed redacted status
while retaining the other diagnostic details. At
test/tap/tests/reg_test_5363_admin_monitor_caching_sha2-t.cpp:263-267, preserve
the password equality assertion but remove both expected and actual password
values from the TAP message.

---

Nitpick comments:
In `@test/tap/tests/reg_test_5363_admin_monitor_caching_sha2-t.cpp`:
- Around line 127-138: Update read_var to wrap the MYSQL_RES returned by
mysql_store_result in a std::unique_ptr with a mysql_free_result deleter,
replacing the manual cleanup while preserving the existing found check and
output assignment.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e6ace944-95c1-4cbc-92c6-f058b927e430

📥 Commits

Reviewing files that changed from the base of the PR and between ca03c8d and 9421d44.

📒 Files selected for processing (5)
  • lib/MySQL_Protocol.cpp
  • test/repro/README.md
  • test/repro/reg_test_5363_admin_monitor_caching_sha2.bash
  • test/repro/reg_test_5985_admin_caching_sha2_full_auth.bash
  • test/tap/tests/reg_test_5363_admin_monitor_caching_sha2-t.cpp
🚧 Files skipped from review as they are similar to previous changes (2)
  • lib/MySQL_Protocol.cpp
  • test/repro/README.md
📜 Review details
⏰ Context from checks skipped due to timeout. (5)
  • GitHub Check: CI-builds / builds (ubuntu22,-tap)
  • GitHub Check: CI-builds / builds (ubuntu24,-tap-genai-gcov)
  • GitHub Check: CI-builds / builds (debian12,-dbg)
  • GitHub Check: run / trigger
  • GitHub Check: build
🧰 Additional context used
📓 Path-based instructions (2)
test/tap/tests/**/*.cpp

📄 CodeRabbit inference engine (CLAUDE.md)

test/tap/tests/**/*.cpp: Test files in test/tap/tests/ must follow the naming pattern test_*.cpp or *-t.cpp.
To add a new TAP test, add the <testname>-t.cpp file and register it in test/tap/tests/Makefile/groups.json; no special Makefile target is needed because make <testname>-t is generated by pattern rule.

Files:

  • test/tap/tests/reg_test_5363_admin_monitor_caching_sha2-t.cpp
**/*.{cpp,h,hpp}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{cpp,h,hpp}: Class names must use PascalCase with protocol prefixes such as MySQL_, PgSQL_, and ProxySQL_.
Member variables must use snake_case.
Constants and macros must use UPPER_SNAKE_CASE.
Use C++17, and gate conditional code with #ifdef PROXYSQL31, #ifdef PROXYSQL40, #ifdef PROXYSQLFFTO, #ifdef PROXYSQLTSDB, and #ifdef PROXYSQLCLICKHOUSE; PROXYSQLGENAI must not guard core code outside plugins/genai/.
Consider performance implications when changing hot paths or other performance-critical code.
Use RAII for resource management and jemalloc for allocation.
Use pthread mutexes for synchronization and std::atomic<> for counters.

Files:

  • test/tap/tests/reg_test_5363_admin_monitor_caching_sha2-t.cpp
🧠 Learnings (1)
📚 Learning: 2026-01-20T09:34:19.124Z
Learnt from: yuji-hatakeyama
Repo: sysown/proxysql PR: 5307
File: test/tap/tests/reg_test_5306-show_warnings_with_comment-t.cpp:39-48
Timestamp: 2026-01-20T09:34:19.124Z
Learning: In ProxySQL's TAP test suite, resource leaks (e.g., not calling mysql_close() on early return paths) are commonly tolerated because test processes are short-lived and OS frees resources on exit. This pattern applies to all C++ test files under test/tap/tests. When reviewing, recognize this as a project-wide test convention and focus on test correctness and isolation rather than insisting on fixing such leaks in these test files.

Applied to files:

  • test/tap/tests/reg_test_5363_admin_monitor_caching_sha2-t.cpp
🪛 GitHub Check: SonarCloud Code Analysis
test/repro/reg_test_5985_admin_caching_sha2_full_auth.bash

[warning] 70-70: Add an explicit return statement at the end of the function.

See more on https://sonarcloud.io/project/issues?id=sysown_proxysql&issues=AZ_g45tqjmTxNrSpeKtz&open=AZ_g45tqjmTxNrSpeKtz&pullRequest=5991

test/repro/reg_test_5363_admin_monitor_caching_sha2.bash

[warning] 83-83: Add an explicit return statement at the end of the function.

See more on https://sonarcloud.io/project/issues?id=sysown_proxysql&issues=AZ_g450_jmTxNrSpeKt0&open=AZ_g450_jmTxNrSpeKt0&pullRequest=5991

🪛 Shellcheck (0.11.0)
test/repro/reg_test_5985_admin_caching_sha2_full_auth.bash

[info] 154-160: This function is never invoked. Check usage (or ignored if invoked indirectly).

(SC2329)


[info] 165-165: Note that A && B || C is not if-then-else. C may run when A is true.

(SC2015)


[info] 210-210: Note that A && B || C is not if-then-else. C may run when A is true.

(SC2015)


[info] 238-238: Note that A && B || C is not if-then-else. C may run when A is true.

(SC2015)

test/repro/reg_test_5363_admin_monitor_caching_sha2.bash

[info] 161-166: This function is never invoked. Check usage (or ignored if invoked indirectly).

(SC2329)


[info] 172-172: Note that A && B || C is not if-then-else. C may run when A is true.

(SC2015)


[info] 175-175: Note that A && B || C is not if-then-else. C may run when A is true.

(SC2015)


[info] 182-182: Note that A && B || C is not if-then-else. C may run when A is true.

(SC2015)

🔇 Additional comments (6)
test/repro/reg_test_5985_admin_caching_sha2_full_auth.bash (4)

58-86: LGTM!


88-99: LGTM!

Also applies to: 101-143


163-169: LGTM!

Also applies to: 180-180


224-224: LGTM!

Also applies to: 237-259

test/tap/tests/reg_test_5363_admin_monitor_caching_sha2-t.cpp (1)

169-171: LGTM!

test/repro/reg_test_5363_admin_monitor_caching_sha2.bash (1)

70-90: LGTM!

Also applies to: 96-107, 129-130, 143-143, 152-160, 169-183, 197-198, 223-228

WORKSPACE="${WORKSPACE:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}"
INFRA_ID="${INFRA_ID:-dev-$USER}"
TAP_GROUP="${TAP_GROUP:-no-infra-g1}"
COLD_START="-e"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Preserve the caller-provided COLD_START value.

Line 69 overwrites COLD_START=1 with -e. The cold-start branch at Line 116 can never run. The usage message at Line 124 is therefore incorrect.

Proposed fix
-COLD_START="-e"
+COLD_START="${COLD_START:-0}"

Also applies to: 116-126

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/repro/reg_test_5363_admin_monitor_caching_sha2.bash` at line 69,
Preserve the caller-provided COLD_START value instead of unconditionally
assigning “-e” near the script’s initialization. Update the cold-start branching
logic around COLD_START and its usage message so the branch remains reachable
when the caller requests a cold start and the displayed invocation matches the
actual accepted value.

Comment on lines +91 to +94
setvar() { # setvar <variable_name> <value> <LOAD statement>
local name="$1" value="$2" load_stmt="$3"
adm "UPDATE global_variables SET variable_value='$value' WHERE variable_name='$name'; $load_stmt" >/dev/null
return $?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Serialize saved variable values safely before restoring them.

Line 93 embeds ORIG_MON_USER and ORIG_MON_PASS directly in an SQL literal. A pre-existing value containing a quote or backslash can produce invalid SQL or restore a different value. This defeats the exact-state restoration added in Lines 157-164.

Encode SQL literal values before constructing the UPDATE statement. Apply the same encoding to name if this helper remains generic.

Also applies to: 161-167

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/repro/reg_test_5363_admin_monitor_caching_sha2.bash` around lines 91 -
94, Update the setvar() helper to SQL-escape or otherwise safely serialize both
value and name before interpolating them into the UPDATE statement, preserving
exact restoration of values containing quotes or backslashes; ensure the same
encoding is used for all calls that restore ORIG_MON_USER and ORIG_MON_PASS.

WORKSPACE="${WORKSPACE:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}"
INFRA_ID="${INFRA_ID:-dev-$USER}"
TAP_GROUP="${TAP_GROUP:-no-infra-g1}"
COLD_START="-e"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Preserve the cold-start setting.

Line 57 overwrites a caller-provided COLD_START=1 with -e. The condition at Line 100 can then never recreate the instance. A warm cache fails preflight instead of running the required cold-cache test.

Proposed fix
-COLD_START="-e"
+COLD_START="${COLD_START:-0}"

Also applies to: 100-110

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/repro/reg_test_5985_admin_caching_sha2_full_auth.bash` at line 57,
Preserve any caller-provided COLD_START value instead of unconditionally
assigning "-e" in the test setup. Update the related logic around the condition
at line 100 so COLD_START=1 still triggers instance recreation and the
cold-cache test runs, while retaining the existing default behavior when no
value is supplied.

Comment on lines +151 to +158
ORIG_ADMIN_CREDS="$(adm 'SELECT @@admin-admin_credentials;')"
ORIG_AUTH_PLUGIN="$(adm 'SELECT @@mysql-default_authentication_plugin;')"

restore() {
adm "UPDATE global_variables SET variable_value='${ORIG_ADMIN_CREDS}' WHERE variable_name='admin-admin_credentials';
LOAD ADMIN VARIABLES TO RUNTIME;
UPDATE global_variables SET variable_value='${ORIG_AUTH_PLUGIN}' WHERE variable_name='mysql-default_authentication_plugin';
${LOAD_MYSQL_VARS}" >/dev/null

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Make configuration capture and restoration lossless.

If either adm query fails, command substitution stores an empty value and the script continues. If an existing value contains a single quote, direct SQL interpolation produces invalid SQL. Lines 202-205 or the EXIT handler can then replace shared Admin configuration with empty or partial data.

Require successful reads before changing state. Capture values as HEX(...), restore them with UNHEX(...), and use the same representation when rebuilding admin-admin_credentials. Calculate EXPECT_LEN from the original byte length.

Also applies to: 198-205

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/repro/reg_test_5985_admin_caching_sha2_full_auth.bash` around lines 151
- 158, Make the configuration snapshot and restore flow lossless: require both
adm reads for ORIG_ADMIN_CREDS and ORIG_AUTH_PLUGIN to succeed before modifying
any state, and capture each value as HEX. Update restore() and the later
admin-admin_credentials reconstruction to restore and reuse values through
UNHEX, escaping no raw quoted data, and calculate EXPECT_LEN from the original
byte length rather than the encoded representation.

Comment on lines +190 to +193
diag("Saved mysql-default_authentication_plugin='%s'%s, mysql-monitor_username='%s'%s, mysql-monitor_password='%s'%s",
orig_plugin.c_str(), have_plugin ? "" : " (UNREADABLE - will not be restored)",
orig_mon_user.c_str(), have_mon_user ? "" : " (UNREADABLE - will not be restored)",
orig_mon_pass.c_str(), have_mon_pass ? "" : " (UNREADABLE - will not be restored)");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Do not write mysql-monitor_password to TAP output.

Line 190 logs the existing monitor password. Line 266 logs it again in the restore assertion. Shared-instance credentials can then persist in CI logs and test artifacts.

  • test/tap/tests/reg_test_5363_admin_monitor_caching_sha2-t.cpp#L190-L193: Replace the password value with a fixed redacted status.
  • test/tap/tests/reg_test_5363_admin_monitor_caching_sha2-t.cpp#L263-L267: Keep the equality check, but remove expected and actual password values from the TAP message.
📍 Affects 1 file
  • test/tap/tests/reg_test_5363_admin_monitor_caching_sha2-t.cpp#L190-L193 (this comment)
  • test/tap/tests/reg_test_5363_admin_monitor_caching_sha2-t.cpp#L263-L267
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/tap/tests/reg_test_5363_admin_monitor_caching_sha2-t.cpp` around lines
190 - 193, The diagnostic at
test/tap/tests/reg_test_5363_admin_monitor_caching_sha2-t.cpp:190-193 must not
output the monitor password; replace its value with a fixed redacted status
while retaining the other diagnostic details. At
test/tap/tests/reg_test_5363_admin_monitor_caching_sha2-t.cpp:263-267, preserve
the password equality assertion but remove both expected and actual password
values from the TAP message.

Brings the branch up to date with v3.0 (14 commits, including the #5993
credential-scope work that already carried this branch's ca03c8d), and
re-triggers a full CI run after the CI-mysql84-g9 job on 9421d44 wedged for
6 hours in test_ssl_fast_forward-3_libmariadb-t.

That stall was not reproducible: the same commit ran mysql84-g9 locally in 26
minutes and the test passed 5/5 in isolation, four other g9 runs completed
successfully inside the same window, and no GitHub Actions incident overlapped
it. Cause still unknown; investigation paused.

Merge verified: lib/MySQL_Protocol.cpp auto-merged keeping both v3.0's
cred_scope_for_session() call sites and this branch's Session/DS argument fix;
the repro scripts and TAP test keep their restore-exact-state versions.
Builds clean under PROXYSQL31.
@sonarqubecloud

sonarqubecloud Bot commented Aug 9, 2026

Copy link
Copy Markdown

@renecannao
renecannao merged commit db0a211 into v3.0 Aug 9, 2026
78 of 81 checks passed
renecannao added a commit that referenced this pull request Aug 9, 2026
Brings the branch up to date with v3.0 (37 commits, including #5991 and the
#5999 salt-length/NUL fixes) and re-triggers a full CI run from a clean state.

Merge verified: lib/MySQL_Protocol.cpp auto-merged keeping all six
auth_response_has() bounds checks from this branch, with the reverted
set_SHA1 const_cast staying reverted; the CACHING_SHA2_PASSWORD() salt-length
and NUL rejections and the deterministic salt sweep come across from v3.0
intact. sqlite3 dep rebuilt against the merged patch; builds clean under
PROXYSQL31.
Snehil-Shah pushed a commit to Snehil-Shah/proxysql that referenced this pull request Aug 9, 2026
TEST_TAP_TIMEOUT could not catch the failure it exists for. The read loop
was:

    line = fop.stdout.readline()          # blocks
    ...
    if tap_timeout > 0 and (time.time() - start_time) > tap_timeout:

readline() blocks until a full line arrives, so a test that hangs while
producing no output never reached the deadline check at all. Verified
directly: with tap_timeout=3 against 'sleep 300', the old loop was still
blocked after 25 seconds; the new one raises at 3.0s.

That is the exact profile of the CI-mysql84-g9 stall on sysown#5991, where
test_ssl_fast_forward-3_libmariadb-t ran for hours.

Replaces the blocking readline() with select() on a bounded wait plus raw
os.read() chunking. select() guarantees the deadline check runs even when
the child is silent; chunking rather than line-reading means a test that
stops mid-line cannot wedge the loop either. Output order and content are
unchanged, a trailing partial line is now flushed instead of dropped, and
decoding uses errors='replace' so a stray non-UTF-8 byte no longer throws.

Verified against four cases: normal chatty test (all lines, in order),
silent hang (timeout fires), partial-line-then-hang (timeout fires), and
clean exit.

Also flips the default from 0 (disabled) to 1800s. 1800 is ~2.4x the
slowest single test measured across 47 groups:

    reg_test_3765_ssl_pollout-t   12.5 min
    test_cluster_sync-t           10.5 min
    set_testing-240-t              7.8 min
    test_auth_methods-t            7.7 min

Only 4 of 401 tests exceed 5 minutes, so this cannot fire on a merely slow
test, while still stopping a hang well inside the 90-minute step budget
added in the companion CI PRs -- and, unlike a step or job timeout, it
identifies WHICH test hung and lets the run continue to its archive steps.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Monitoring failing after enabling caching_sha2_password globally

1 participant