models/UserModel.php::syncUserFromAuthelia() (~lines 78-117) does a plain check-then-insert (SELECT ... WHERE username = ? → if 0 rows, INSERT) with no transaction and no INSERT ... ON DUPLICATE KEY. users.username has a UNIQUE KEY constraint, and mysqli throws mysqli_sql_exception on constraint violation under PHP 8.1+'s default report mode (per an existing comment in helpers/Database.php).
Impact: Two simultaneous first-visit requests for the same brand-new user (e.g. two browser tabs opened right after completing SSO login) race: the second INSERT throws a duplicate-key exception, uncaught anywhere in syncUserFromAuthelia(), AuthMiddleware::authenticate(), or index.php (no try/catch around AuthMiddleware usage, and ErrorHandler::init() isn't wired in here either, consistent with the previously-filed finding that ErrorHandler is barely used app-wide). Result: an uncaught fatal error on the losing request, with stack-trace exposure depending on the server's global display_errors setting — on the authentication path itself. Self-heals on page reload since the winning row now exists.
Fix: Wrap the insert in INSERT ... ON DUPLICATE KEY UPDATE (updating the sync'd fields), or catch the duplicate-key exception and re-fetch the now-existing row.
**Severity:** Low/Medium
`models/UserModel.php::syncUserFromAuthelia()` (~lines 78-117) does a plain check-then-insert (`SELECT ... WHERE username = ?` → if 0 rows, `INSERT`) with no transaction and no `INSERT ... ON DUPLICATE KEY`. `users.username` has a `UNIQUE KEY` constraint, and mysqli throws `mysqli_sql_exception` on constraint violation under PHP 8.1+'s default report mode (per an existing comment in `helpers/Database.php`).
**Impact:** Two simultaneous first-visit requests for the same brand-new user (e.g. two browser tabs opened right after completing SSO login) race: the second `INSERT` throws a duplicate-key exception, uncaught anywhere in `syncUserFromAuthelia()`, `AuthMiddleware::authenticate()`, or `index.php` (no try/catch around `AuthMiddleware` usage, and `ErrorHandler::init()` isn't wired in here either, consistent with the previously-filed finding that `ErrorHandler` is barely used app-wide). Result: an uncaught fatal error on the losing request, with stack-trace exposure depending on the server's global `display_errors` setting — on the authentication path itself. Self-heals on page reload since the winning row now exists.
**Fix:** Wrap the insert in `INSERT ... ON DUPLICATE KEY UPDATE` (updating the sync'd fields), or catch the duplicate-key exception and re-fetch the now-existing row.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Severity: Low/Medium
models/UserModel.php::syncUserFromAuthelia()(~lines 78-117) does a plain check-then-insert (SELECT ... WHERE username = ?→ if 0 rows,INSERT) with no transaction and noINSERT ... ON DUPLICATE KEY.users.usernamehas aUNIQUE KEYconstraint, and mysqli throwsmysqli_sql_exceptionon constraint violation under PHP 8.1+'s default report mode (per an existing comment inhelpers/Database.php).Impact: Two simultaneous first-visit requests for the same brand-new user (e.g. two browser tabs opened right after completing SSO login) race: the second
INSERTthrows a duplicate-key exception, uncaught anywhere insyncUserFromAuthelia(),AuthMiddleware::authenticate(), orindex.php(no try/catch aroundAuthMiddlewareusage, andErrorHandler::init()isn't wired in here either, consistent with the previously-filed finding thatErrorHandleris barely used app-wide). Result: an uncaught fatal error on the losing request, with stack-trace exposure depending on the server's globaldisplay_errorssetting — on the authentication path itself. Self-heals on page reload since the winning row now exists.Fix: Wrap the insert in
INSERT ... ON DUPLICATE KEY UPDATE(updating the sync'd fields), or catch the duplicate-key exception and re-fetch the now-existing row.