phpMyFAQ has SQL Injection in CurrentUser::setTokenData through unescaped OAuth token fields
Date: 2026-05
Affected: composer/phpmyfaq/phpmyfaq, composer/thorsten/phpmyfaq
Attack vector: sql-injection
Category: vulnerability-disclosure
Severity: High
CVE: CVE-2026-46359
CWE: CWE-89
CVSS: 7.5 (CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H)

## Summary `CurrentUser::setTokenData()` in `phpmyfaq/src/phpMyFAQ/User/CurrentUser.php` at lines 515-534 builds a SQL UPDATE statement with `sprintf` and interpolates OAuth token fields (`refresh_token`, `access_token`, `code_verifier`, and `json_encode($token['jwt'])`) without calling `$db->escape()`. Sibling methods `setAuthSource()` and `setRememberMe()` in the same file do call `$db->escape()` on user-controlled values, so the omission is local to this method. An attacker (Bob) whose Azure AD display name contains a single quote (for example `O'Brien`, or a deliberate SQL payload) breaks out of the string literal and injects arbitrary SQL against the phpMyFAQ database. ## Details **Vulnerable code** (`phpmyfaq/src/phpMyFAQ/User/CurrentUser.php`, lines 513-534): ```php public function setTokenData(#[\SensitiveParameter] array $token): bool { $update = sprintf( " UPDATE %sfaquser SET refresh_token = '%s', access_token = '%s', code_verifier = '%s', jwt = '%s' WHERE user_id = %d", Database::getTablePrefix(), $token['refresh_token'], $token['access_token'], $token['code_verifier'], json_encode($token['jwt'], JSON_THROW_ON_ERROR), $this->getUserId(), ); return (bool) $this->configuration->getDb()->query($update); } ``` `json_encode()` does NOT escape single quotes. A JWT claim such as `{"preferred_username": "


Mitigations:

Architectural layers (MAESTRO):