Skip to content

Security(M-02): authorization revocation fails open on Keycloak refresh/Admin API errors #170

Description

@dcmcand

Summary

Authorization revocation fails open during Keycloak errors. A transient refresh failure keeps the current auth state, and a failed Admin API query after a successful token refresh preserves the previous mount and profile grants. There is no maximum age on stale grants, so a revoked user can retain access for as long as the Admin API keeps erroring.

Severity: Medium · CWE-754 (Improper Handling of Exceptional Conditions)
Validation: Confirmed against HEAD f932d80 on 2026-07-14 (assessed at 69c84f7; unchanged since).

Evidence

  • config/jupyterhub/00-gateway-auth.py:359-363: on a transient refresh error, refresh_user logs and return True, keeping the current auth state. Only 400 invalid_grant returns False and forces re-login (00-gateway-auth.py:353-358).
  • After a successful refresh, a failed group query preserves the old set: 00-gateway-auth.py:387-396 restores groups_with_permission_to_mount; 00-gateway-auth.py:406-414 does the same for allowed_jupyterlab_profiles.
  • Initial login fails closed: update_auth_model sets filtered = [] on Admin API failure (00-gateway-auth.py:445-452) and _resolve_allowed_profiles returns [] on failure (00-gateway-auth.py:472-478).
  • No max stale-grant age: refresh_user has no timestamp or age comparison; preservation is unconditional on old_* is not None.

Impact

A user removed from a shared-storage role or a restricted profile keeps that access across every subsequent refresh while the Keycloak Admin API is unavailable. The initial-login path is safe; the gap is mid-session refresh.

Remediation

  • Timestamp the last successful authorization evaluation.
  • Apply a short maximum age for sensitive mounts and profiles, and fail closed past that age while still allowing lower-risk login where appropriate.
  • Consume Keycloak identity events where available.
  • Alert on stale authorization state.

Acceptance criteria

  • Role removal takes effect within a documented interval even during an Admin API outage.
  • Stale authorization age is observable.

Source: data-science-pack 0.1.0 security assessment (pinned commit 69c84f72df259ec755ed40bfc83f20158c550d55), finding M-02.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: securitySecurity findings and hardening workpriority: medium ⚡Medium priority - standard queue

    Type

    No type

    Fields

    Priority

    None yet

    Start date

    None yet

    Target date

    None yet

    Size

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions