nebari-dev / nebari-dev/data-science-pack
Security(M-02): authorization revocation fails open on Keycloak refresh/Admin API errors
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 5
- Forks
- 7
- Avg merge
- 1d 20h
- Merged PRs (30d)
- 13
Description
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_userlogs andreturn True, keeping the current auth state. Only400 invalid_grantreturnsFalseand 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-396restoresgroups_with_permission_to_mount;00-gateway-auth.py:406-414does the same forallowed_jupyterlab_profiles. - Initial login fails closed:
update_auth_modelsetsfiltered = []on Admin API failure (00-gateway-auth.py:445-452) and_resolve_allowed_profilesreturns[]on failure (00-gateway-auth.py:472-478). - No max stale-grant age:
refresh_userhas no timestamp or age comparison; preservation is unconditional onold_* 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.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in config/jupyterhub/00-gateway-auth.py at refresh_user, then trace update_auth_model and _resolve_allowed_profiles, comparing the cited refresh and initial-login error paths. Review how authorization state is stored and evaluated, then use the acceptance criteria to verify bounded stale-grant access and observable authorization age.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- authorization, security
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100