#15049·AutoGPT

External API key validation: per-request scrypt with no rate limiting

Author: Victor725Created Sep 30, 2026Updated Sep 30, 2026

⚠️ Search for existing issues first ⚠️

  • I have searched the existing issues, and there is no existing issue for my problem

Which Operating System are you using?

Docker

Which version of AutoGPT are you using?

Master (branch)

What LLM Provider do you use?

Other (detail in issue)

Which area covers your issue best?

Other

What commit or version are you using?

c035ab1f91b8556f86e87be26dcaf31677f64ba5

Describe your issue.

External API keys are agpt_ + 43 random characters; the first 8 — i.e. agpt_ + 3 random chars, the head — are stored in plaintext and used to look up candidate keys in the DB (get_active_api_keys_by_head), and the full key is then verified with scrypt (n=2^14, r=8, p=1, ~16 MB working memory per verification). Consequently, every request whose head matches a stored key runs a full scrypt verification per matched candidate — even when the rest of the key is garbage and the request is guaranteed to fail — and nothing on this path is rate-limited. An attacker only needs a head that matches some stored key (e.g. the head of their own free account's key), and with only 64³ = 262,144 possible heads the whole head space is enumerable even without owning any key; the server can be made to burn CPU and memory at request rate, starving the shared external API for all users.

Expected behavior

Authentication failure is cheap and bounded — an invalid key is rejected quickly without expensive crypto, and abusive request rates are throttled (429, per IP or per key), so an unauthenticated caller cannot drive up the per-request server cost.

Actual behavior (measured, in-container against /external-api/v1/integrations/providers)

# Test (20 serial unless noted) What it shows Avg latency/req Status
1 Valid API key the auth path itself: full scrypt runs on every request (the 403 is the permission layer rejecting this key's scopes, i.e. after auth) 35 ms 403
2 Valid head + garbage rest-of-key the attack: the head matches a stored key, so full scrypt runs although the request is guaranteed to fail 30 ms 401
3 Unknown head (agpt_zzz…) — control no DB head match → no scrypt, cheap rejection 8 ms 401
4 200 concurrent requests, valid head + garbage rest no rate limiting anywhere on the path — 200 × 401, 0 × 429

The ~4× latency gap between rows 2 and 3 is the per-request scrypt cost, paid on every head-matched request regardless of outcome, and row 4 shows it can be driven at concurrent request rate. The attacker needs no one else's key: registering a free account already reveals the head of one's own key.

Upload Activity Log Content

No response

Upload Error Log Content

No response

Source: Significant-Gravitas/AutoGPT