VYPR
Unrated severityNVD Advisory· Published Jun 1, 2026

CVE-2026-48726

CVE-2026-48726

Description

Apache Airflow's FabAuthManager/KeycloakAuthManager logout fails to revoke JWT, allowing continued API access.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Apache Airflow's FabAuthManager/KeycloakAuthManager logout fails to revoke JWT, allowing continued API access.

Vulnerability

A bug in Apache Airflow's FabAuthManager and KeycloakAuthManager logout handling leaves previously-issued JWT tokens valid after a user logs out via the UI. The /auth/logout endpoint short-circuits when the auth manager's get_url_logout() returns a URL, bypassing the revoke_token() call. As a result, the JWT remains accepted by the API server until its natural expiry. This affects deployments configured with FabAuthManager or KeycloakAuthManager (the bug does not affect SimpleAuthManager). The fix for CVE-2025-57735 (PR #57992 / PR #61339) addressed cookie-side invalidation but did not cover this provider-side reachability issue. Versions prior to apache-airflow 3.2.2 are affected [1].

Exploitation

An attacker who possesses a previously-issued JWT for a logged-out user can make authenticated API calls as that user. The attacker needs network access to the Airflow API server and a valid JWT that has not yet expired. No additional authentication or user interaction is required once the token is held. The logout flow does not revoke the token, so the token remains usable until its natural expiry [1].

Impact

Successful exploitation allows an attacker to maintain authenticated API access as the logged-out user. This can lead to unauthorized information disclosure, data modification, or privilege escalation depending on the permissions of the compromised user. The attacker gains the same level of access that the user had before logout, violating the intended confidentiality and integrity guarantees of the logout mechanism [1].

Mitigation

The fix is included in Apache Airflow version 3.2.2 and later. Users who already upgraded for CVE-2025-57735 should additionally upgrade to 3.2.2 or later to cover the FAB/Keycloak logout paths. No workaround is available; upgrading is the recommended mitigation. The vulnerability is not listed on the CISA Known Exploited Vulnerabilities (KEV) catalog as of the publication date [1].

AI Insight generated on Jun 1, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

1

Patches

2
b1aec757ce1e

Revoke JWT on /auth/logout regardless of auth manager logout URL (#67289)

https://github.com/apache/airflowPierre JeambrunMay 22, 2026via nvd-ref
2 files changed · +29 4
  • airflow-core/src/airflow/api_fastapi/core_api/routes/public/auth.py+5 4 modified
    @@ -57,14 +57,15 @@ def login(request: Request, auth_manager: AuthManagerDep, next: None | str = Non
     )
     def logout(request: Request, auth_manager: AuthManagerDep) -> RedirectResponse:
         """Logout the user."""
    +    # Revoke the current token before any redirect or cookie deletion so the JWT
    +    # is invalidated even when the auth manager redirects to an external logout URL.
    +    if token_str := request.cookies.get(COOKIE_NAME_JWT_TOKEN):
    +        auth_manager.revoke_token(token_str)
    +
         logout_url = auth_manager.get_url_logout()
         if logout_url:
             return RedirectResponse(logout_url)
     
    -    # Revoke the current token before deleting the cookie
    -    if token_str := request.cookies.get(COOKIE_NAME_JWT_TOKEN):
    -        auth_manager.revoke_token(token_str)
    -
         secure = request.base_url.scheme == "https" or bool(conf.get("api", "ssl_cert", fallback=""))
         cookie_path = get_cookie_path()
         response = RedirectResponse(auth_manager.get_url_login())
    
  • airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_auth.py+24 0 modified
    @@ -220,3 +220,27 @@ def test_logout_without_cookie_does_not_revoke(self, logout_client):
     
             assert response.status_code == 307
             assert RevokedToken.is_revoked("nonexistent-jti") is False
    +
    +    def test_logout_revokes_token_when_logout_url_redirects(self, logout_client):
    +        """Token must be revoked before the redirect when get_url_logout returns a URL."""
    +        now = int(time.time())
    +        auth_manager = logout_client.app.state.auth_manager
    +        signer = auth_manager._get_token_signer()
    +        token_payload = {
    +            "sub": "admin",
    +            "jti": "test-jti-redirect-456",
    +            "exp": now + 3600,
    +            "iat": now,
    +            "nbf": now,
    +            "aud": "apache-airflow",
    +            "iss": signer.issuer,
    +        }
    +        token_str = jwt.encode(token_payload, signer._secret_key, algorithm=signer.algorithm)
    +
    +        logout_client.cookies.set(COOKIE_NAME_JWT_TOKEN, token_str)
    +        with patch.object(auth_manager, "get_url_logout", return_value="http://external/logout"):
    +            response = logout_client.get("/auth/logout", follow_redirects=False)
    +
    +        assert response.status_code == 307
    +        assert response.headers["location"] == "http://external/logout"
    +        assert RevokedToken.is_revoked("test-jti-redirect-456") is True
    
cde4885818be

Updating release notes for 3.2.2rc3

https://github.com/apache/airflowvatsrahul1001May 26, 2026Fixed in 3.2.2via release-tag
2 files changed · +5 4
  • RELEASE_NOTES.rst+3 2 modified
    @@ -24,7 +24,7 @@
     
     .. towncrier release notes start
     
    -Airflow 3.2.2 (2026-05-27)
    +Airflow 3.2.2 (2026-05-29)
     --------------------------
     
     Significant Changes
    @@ -81,7 +81,8 @@ Significant Changes
     
     Bug Fixes
     ^^^^^^^^^
    -
    +- Fix ``Callback.handle_event`` triggerer crash when OpenTelemetry metrics receive dict typed tag values (#67527) (#67529)
    +- UI: Rewrite ``modulepreload hrefs`` to the api-server static path (#67548) (#67556)
     - Correctly pre-allocate ``external_executor_id`` with multiple executors on PostgreSQL (#67388) (#67458)
     - Return raw import-error stacktrace when a Dag file has no registered Dag (#67465) (#67478)
     - UI: Fix Expand/Collapse All on XComs and Audit Log JSON cells (#67316) (#67361)
    
  • reproducible_build.yaml+2 2 modified
    @@ -1,2 +1,2 @@
    -release-notes-hash: 6407b48d1054fe3ce68c09bf4435d91d
    -source-date-epoch: 1779745327
    +release-notes-hash: 504288db9a9dc13a0db859232fab98d0
    +source-date-epoch: 1779811737
    

Vulnerability mechanics

No source-code context for this CVE — mechanics is only generated when we can read the actual fix diff. Without that, the four sections (root cause, attack vector, affected code, fix) would be speculation rather than analysis.

References

3

News mentions

0

No linked articles in our index yet.