Skip to content

Fix API Key Limit Race Condition Bypass#5620

Open
rossnoah wants to merge 1 commit into
pterodactyl:1.0-developfrom
rossnoah:1.0-develop
Open

Fix API Key Limit Race Condition Bypass#5620
rossnoah wants to merge 1 commit into
pterodactyl:1.0-developfrom
rossnoah:1.0-develop

Conversation

@rossnoah
Copy link
Copy Markdown

@rossnoah rossnoah commented Apr 9, 2026

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:

(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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant