Aias00 opened a new pull request, #4260:
URL: https://github.com/apache/hertzbeat/pull/4260
## Summary
Fixes a silent TLS-to-plaintext downgrade in the R2DBC MySQL collector route.
### Vulnerability
`MysqlR2dbcQueryExecutor.execute` first tried `SslMode.PREFERRED`; if that
errored with a handshake-style failure (`handshake_failure`, `ssl/tls
handshake`, `ClosedChannelException`, `connection unexpectedly closed`), it
retried with `SslMode.DISABLED`:
```java
QueryResult firstAttempt = executeOnce(normalizedSql, options,
SslMode.PREFERRED);
if (!firstAttempt.hasError() ||
!shouldRetryWithoutSsl(firstAttempt.getError())) {
return firstAttempt;
}
QueryResult fallbackAttempt = executeOnce(normalizedSql, options,
SslMode.DISABLED);
```
A TLS handshake failure is **ambiguous** — a MitM can deliberately disrupt
the handshake to trigger this fallback. Retrying with SSL disabled then
authenticates the monitoring user to the (possibly tampered) endpoint over
plaintext, exposing the credentials. Classic SSL-strip/downgrade.
### Fix
Drop the error-triggered `DISABLED` retry and surface the failure instead.
`SslMode.PREFERRED` already handles the legitimate plaintext case safely:
when the server advertises no SSL capability in the initial handshake, the
driver falls back to plaintext via protocol negotiation **without error**. So
the explicit `DISABLED` retry only ever fired on errors — exactly the unsafe
path. The `caching_sha2_password` / `must require ssl` diagnostic is preserved
(now checked against the single attempt's error).
### Behavior after the fix
| Server | Before | After |
|---|---|---|
| Supports TLS | TLS ✅ | TLS ✅ |
| No SSL capability (clean) | plaintext via PREFERRED ✅ | plaintext via
PREFERRED ✅ (unchanged) |
| TLS handshake *fails* | **downgrade to plaintext** ❌ | fail closed with
the error ✅ |
| `caching_sha2_password`, runtime can't TLS | tailored error message |
tailored error message (unchanged) |
The only behavior change is the third row — the dangerous one — which now
fails closed.
### Verification
- `mvn -pl hertzbeat-collector/hertzbeat-collector-mysql-r2dbc -am compile`
✅ (JDK 25)
- `mvn -pl hertzbeat-collector/hertzbeat-collector-mysql-r2dbc -am
checkstyle:check` ✅
- Unit tests pass: `SqlGuardTest`, `ResultSetMapperTest`,
`MysqlSqlTemplateCompatibilityTest` (7 tests) ✅
- The Docker-based `MysqlR2dbcQueryExecutorIntegrationTest` exercises the
success paths (no-SSL and SSL-capable servers) via `PREFERRED` and is
unaffected by this change; it requires Docker so was not run locally.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]