michaelbromley / michaelbromley/sherlock

MySQL: caching_sha2_password auth fails — driver appears not to support MySQL 8 default

Open
#9 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
8
Forks
3
PR merge metrics
No merged PRs in 30d

Description

## Summary

Sherlock 1.3.0 fails to authenticate against MySQL 8 users that use the default `caching_sha2_password` plugin, even with correct credentials and a working network path. The same credentials over the same TCP connection succeed with the native `mysql` CLI, so this looks like a driver-level limitation rather than a config issue.

## Environment

- Sherlock: `1.3.0` (macOS arm64 binary)
- MySQL server: `8.0.x`
- Connection path: plain TCP (no TLS), via loopback

## Repro

1. Have a MySQL 8 user using the default plugin:
```sql
CREATE USER 'demo'@'%' IDENTIFIED BY 'pw';
-- → IDENTIFIED WITH 'caching_sha2_password' (the 8.x default)
GRANT SELECT ON some_db.* TO 'demo'@'%';
```
2. Configure a sherlock connection (or use `--url`) with these credentials.
3. Run any query.

**Result:** `Access denied for user 'demo'@'' (using password: YES)`.

**Expected:** Connect and run the query.

**Cross-check (same host, same creds, native client):**
```
mysql --protocol=TCP -h 127.0.0.1 -u demo -p'pw' -e 'SELECT 1' some_db
# 1
# 1
```
Native client works → creds and network are fine.

**Workaround:** create / alter the user to use `mysql_native_password`:
```sql
ALTER USER 'demo'@'%' IDENTIFIED WITH mysql_native_password BY 'pw';
```
Sherlock then connects fine. But `mysql_native_password` is deprecated as of MySQL 8.4 and removed thereafter, so this isn't a long-term answer.

## What I tried (none helped)

- Various URL params (`?sslmode=disable`, `?ssl=true`, `?allowPublicKeyRetrieval=true`, `?authentication-plugin=mysql_native_password`)
- Confirmed the password parser handles the credentials correctly: with a wrong password sherlock reports `using password: YES`, with no password it reports `using password: NO`. So the password is being sent — auth just fails.

## Diagnosis

`caching_sha2_password` requires either:
1. A TLS-encrypted connection (so the server can ask for the password in the clear), or
2. The server's RSA public key (so the client can encrypt the password before sending) — typically retrieved with `allowPublicKeyRetrieval=true` (or equivalent), unless the public key is shipped with the client.

Older MySQL drivers don't implement either path over a plain TCP connection and fall back to `mysql_native_password`-style hashing, which the server rejects → "Access denied" with no further hint.

## Suggested fix

Upgrade the bundled MySQL driver to a version that handles `caching_sha2_password` over plaintext (server public-key retrieval), or expose a `caching_sha2_password` / `allowPublicKeyRetrieval`-style flag in the connection config.

Happy to help test a fix.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

No repository file or test is named. Start by reproducing the plain-TCP failure against MySQL 8.0 using the supplied `--url` or connection configuration, then locate the bundled MySQL driver and its authentication path. Done means a `caching_sha2_password` user can connect and run the query without requiring the deprecated `mysql_native_password` workaround.

Written by the indexing model from the issue text.

Assessment

Tech stack
mysql
Domain
authentication, database
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.