The API key creation endpoint checks that a user has fewer than 25 keys
before creating a new one. The problem is that the count was read from
an eager-loaded collection (`$user->apiKeys->count()`) with no lock
held, so concurrent requests could both pass the check and each create a
key, pushing the user past the 25-key cap.
The fix wraps the count check and key creation in a single database
transaction with `lockForUpdate()` on the query. Only one request at a
time can evaluate and modify the count, closing the race window.
### Proof of Concept
Run this in the browser console while authenticated with a user that has
24 API keys:
```js
(async () => {
const makeKey = (desc) => fetch('/api/client/account/api-keys', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest',
'X-XSRF-TOKEN':
decodeURIComponent(document.cookie.match(/XSRF-TOKEN=([^;]+)/)[1]),
},
body: JSON.stringify({ description: desc, allowed_ips: [] }),
});
const [r1, r2] = await Promise.all([makeKey('0024'), makeKey('0025')]);
console.log('0024:', r1.status, (await r1.text()).slice(0, 200));
console.log('0025:', r2.status, (await r2.text()).slice(0, 200));
})();
```
On the old code, both requests can return 200 (you may need to run this
a few times to hit the race window). After the fix, the second request
correctly returns a 400 error.
This change applies a rate limit to account email changes to prevent
enumeration on the system. The throttle is applied at the account level.
Administrators can still update an account's email address manually to
bypass this restriction if/when necessary.
- Fixes issue where the panel would create activity logs even when the
value didn't change
- Log an empty string instead of displaying "null" when the variable is
empty
Closes#5604
This expands upon previous work done to better disconnect users from
SFTP when different events occur within Pterodactyl. This new logic also
accounts for password changes and their account being deleted entirely
from the system.
These events now trigger background jobs that will reach out to every
node they are associated with to ensure they're disconnected if
currently connected.
* Add throttling to resource creation endpoints
* Fix middleware registration for the throttlers
* Lock the server's resource models when adding new ones
* Throttle subusers even more
---------
Co-authored-by: DaneEveritt <dane@daneeveritt.com>