PT-2026-117593
Publicado
2026-10-09
·
Atualizado
2026-10-09
Descrição por
CVSS 3.1
8.1
AltaMétricasAV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
Summary
The API-key cache in
check apikey() allows an attacker to authenticate with a forged API key as long as the legitimate key for the same key id has been used recently.On a cache hit, the API key secret is never verified, resulting in a complete authentication bypass during the cache lifetime.
Affected Components
-
src/pyload/core/api/init.py -
Api.check apikey() -
src/pyload/core/database/apikey database.py -
check apikey() -
check key()
The cache is used by normal API requests through:
src/pyload/webui/app/helpers.py
which calls:
python
api.check apikey(api key)without providing a
ttl, meaning the default 300-second cache is always enabled.Root Cause
Successful API key validations are cached in:
python
self. apikey cacheusing the following structure:
python
{
key id: (timestamp, cached data)
}The cache key is based only on
key id, and that value is parsed directly from the user-supplied API key rather than being obtained from a trusted lookup.When a cache hit occurs within the TTL,
check apikey() returns:python
{
"success": True,
"data": cached data
}after checking only:
expires at
At no point on this execution path is the supplied secret:
text
apikey[-43:]compared against the stored key hash.
The actual secret verification exists only in:
python
check key()which correctly uses:
python
hmac.compare digest()However, this function is only reached on a cache miss through the database layer's
check apikey() implementation.Furthermore, the cached object cannot be used for verification because it intentionally does not include the stored key hash.
The cached record contains only:
iduser idnamecreated atexpires atlast used
Since
key hash is absent, the cache lacks the information required to validate the presented secret.As a result, once a legitimate request populates the cache, every subsequent request using the same
key id within the 300-second cache window is accepted without validating the secret.Impact
key id values are small sequential integers assigned when API keys are created (1, 2, 3, ...), making them trivial to enumerate.The API key format is also publicly reconstructable from the source code.
An attacker therefore does not need to know any valid API key secret.
They only need a
key id whose legitimate key has been used within the previous five minutes, which is likely on an actively used deployment.During that cache window, a forged API key follows exactly the same authentication path as a legitimate key and inherits the associated user's permissions.
This results in a complete remote authentication bypass.
I would classify the issue as Critical severity.
Estimated CVSS v3.1
AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H(
AC:H only because successful exploitation depends on the cache already containing an entry.)Reproduction
1. Create an administrator account.
2. Generate an API key.
Example:
text
pl 11<43-character-secret>where:
key id = 13. Send a legitimate authenticated request.
bash
curl
-H "X-API-Key: pl 11<real-43-char-secret>"
http://127.0.0.1:8000/api/statusExpected response:
text
HTTP/1.1 200 OK4. Within 300 seconds, send the same request using a forged API key.
bash
curl
-H "X-API-Key: pl 11xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
http://127.0.0.1:8000/api/statusObserved response:
text
HTTP/1.1 200 OKThe request succeeds even though the API key secret is entirely incorrect.
Control Test
If the forged API key is sent before any legitimate request has populated the cache, the server correctly returns:
text
HTTP/1.1 401 UnauthorizedThe only difference between the failing and succeeding forged request is whether the cache already contains an entry for that
key id.This isolates the vulnerability specifically to the cache-hit path.
Suggested Fix
Cache hits should never replace secret verification.
Possible approaches include:
-
Store a value derived from the complete API key (or its hash) in the cache and verify it using
hmac.compare digest()on every cache hit before returning success. -
Alternatively, key the cache using a value derived from the entire API key secret (for example, a cryptographic hash of the complete API key) rather than using only
key id.
Regardless of implementation, the security invariant should remain:
The API key secret must be validated on every authenticated request, regardless of whether the cache is hit or missed.
Explorabilidade
Correção
Impactos
Fornecedores
Produtos afetados
Identificadores relacionados
Encontrou algum problema na descrição? Tem algo a acrescentar? Fique à vontade para nos escrever 👾