mirror of
https://github.com/myronblair/novacpx
synced 2026-06-30 17:50:41 -05:00
fix: all code review security findings
- CORS: replace open regex with explicit hostname allowlist + port whitelist - Exception handler: only expose RuntimeException/InvalidArgumentException messages; PDOException and others return generic 'internal error' - Auth::portalUrl(): allowlist-validate HTTP_HOST before using it in redirect URL — prevents open redirect via Host header injection - _branding.php custom_css: strip HTML tags, js: URLs, @import, expression() instead of just </style> which was trivially bypassable - accounts create: check accounts table as well as users for username uniqueness (TOCTOU fix); wrap user INSERT + provisioning in single transaction so rollback is atomic on failure Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LP9Q4kfCAYAjJnsbHBrViZ
This commit is contained in:
@@ -71,9 +71,12 @@ match ($action) {
|
||||
|
||||
if (!filter_var($body['email'], FILTER_VALIDATE_EMAIL)) Response::error("Invalid email address");
|
||||
if ($db->fetchOne("SELECT id FROM users WHERE email = ? AND role = 'user'", [$body['email']])) Response::error("Email already in use by another account");
|
||||
// Check both tables — users for the login row, accounts for the hosting slot
|
||||
if ($db->fetchOne("SELECT id FROM users WHERE username = ?", [$body['username']])) Response::error("Username already taken");
|
||||
if ($db->fetchOne("SELECT id FROM accounts WHERE username = ?", [$body['username']])) Response::error("Username already taken");
|
||||
|
||||
// Insert user first — AccountManager::create() wraps everything else in its own transaction
|
||||
// Wrap user insert + provisioning in a transaction so cleanup is atomic
|
||||
$db->beginTransaction();
|
||||
$userId = (int)$db->insert(
|
||||
"INSERT INTO users (username, password, email, role, status, reseller_id) VALUES (?,?,?,?,?,?)",
|
||||
[
|
||||
@@ -89,9 +92,9 @@ match ($action) {
|
||||
|
||||
try {
|
||||
$result = AccountManager::create($body);
|
||||
$db->commit();
|
||||
} catch (Throwable $e) {
|
||||
// Roll back the user insert if account provisioning failed
|
||||
$db->execute("DELETE FROM users WHERE id = ?", [$userId]);
|
||||
$db->rollBack();
|
||||
throw $e;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user