Skip to content

Suspending an already revoked API key overwrites REVOKED with SUSPENDED #15296

Description

@capy-ai

Summary

suspend_api_key writes status=SUSPENDED without looking at the key's current status. Calling POST /api/api-keys/{key_id}/suspend on a key that is already REVOKED turns it into a SUSPENDED key (while revokedAt stays set), so a terminal state is overwritten and the key's listed status is wrong.

Affected code

autogpt_platform/backend/backend/data/auth/api_key.py — suspend_api_key (L244-269), route POST /{key_id}/suspend in backend/api/features/api_keys/routes.py. Related: revoke_api_key (L170) re-stamps revokedAt on an already revoked key, and update_api_key_permissions (L287) edits revoked keys.

Trigger / steps

  1. Create an API key, revoke it (DELETE /api/api-keys/{id}).
  2. POST /api/api-keys/{id}/suspend.
  3. GET /api/api-keys/{id}.

Expected vs actual

  • Expected: 4xx (a revoked key cannot be suspended), status stays REVOKED.
  • Actual: 200, status is SUSPENDED and revoked_at is still set. validate_api_key only accepts ACTIVE keys, so the key stays unusable today; but the UI/audit trail now reports a revoked key as merely suspended, and any future "reactivate" action for suspended keys would resurrect a key the owner had revoked.

Severity: low

No authentication bypass today (only ACTIVE keys validate); it is state corruption on a security-relevant record.

How I confirmed it

Ran the real create_api_key → revoke_api_key → suspend_api_key → update_api_key_permissions → revoke_api_key against a local Postgres with all migrations applied: after suspend the status is SUSPENDED with revoked_at still set; permissions can still be changed on the revoked/suspended key; revoking again overwrites revokedAt. Did not call the HTTP routes.

Fix feasible: yes

Reject suspend/permission-update when status is REVOKED (and make revoke idempotent) using a conditional update_many(where={"id": ..., "status": ACTIVE}).

Activity

  1. ntindle commented on Oct 8, 2026

    @ntindle
    Member

    Backfill validation: reproduced

    Image: significantgravitas/autogpt:latest @ sha256:122929723f57b8927af016d606ae21b21c03a012c2de1d9c30b1c8359e9157f1 (Hub v0.8.3 / sha-73cae306b4f6b197d2e1eaaa3162c326ec0ab076 / oci_revision 73cae306b4f6b197d2e1eaaa3162c326ec0ab076), pulled 2026-10-08 13:08 CT (ok_up_to_date), run sweep-20261008T1808.

    Verdict: reproduced (real data-layer functions against the in-image Postgres)

    What we checked

    Real create_api_key → revoke_api_key (status REVOKED) → suspend_api_key returns SUSPENDED. The DB row is now SUSPENDED with revokedAt still set.

    Limits

    Data layer only.

    Suggestion

    Reject suspend (and permission edits) on REVOKED keys.

    Host evidence: /workspace/autogpt-backfill/evidence/15296/sweep-20261008T1808/ (host-local)

  2. added a commit that references this issue on Oct 9, 2026
    62400de
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions