Vulnerability Analysis

CVE-2026-18963: Critical Keycloak Password Reset Bypass Enables Unauthenticated Account Takeover

Executive Summary

CVE-2026-18963 is a critical authentication bypass vulnerability in Keycloak's reset-credentials flow that allows any unauthenticated attacker to take over any user account — including administrator accounts — without ever sending or clicking a verification email. Disclosed publicly in August 2026 with a CVSS score of 9.1, the flaw stems from broken state validation in the credential reset workflow and affects all deployments of upstream Keycloak prior to version 26.7.2, as well as Red Hat build of Keycloak before versions 26.4.15 and 26.6.6. Organizations running Keycloak as an identity provider should treat patching as an emergency priority.


1. What Is This Vulnerability?

Keycloak is one of the most widely deployed open-source Identity and Access Management (IAM) platforms in the world. It provides single sign-on (SSO), OAuth 2.0, and OpenID Connect capabilities for thousands of enterprise applications. The reset-credentials authentication flow is what drives the "Forgot Password" feature: a user enters their username, Keycloak sends a verification email containing a one-time action token, and the user clicks that link to prove email ownership before being allowed to set a new password.

CVE-2026-18963 breaks the integrity of that entire chain.

The Root Cause

The flaw lives inside keycloak-services, the core engine driving the authentication flow logic. Keycloak tracks which step of the reset-credentials flow is currently active, but it does so in a way that is not cryptographically bound to the step that set the state. Specifically, the ResetCredentialEmail.action() handler — the component that is supposed to validate the email action token — can be induced to return a success result without actually verifying that the token was ever clicked.

Because the flow state is not properly anchored, an attacker can manipulate the sequence of HTTP requests to "skip" the email verification step entirely and jump directly to the password-setting step. Keycloak accepts this manipulated state as legitimate and proceeds to update credentials.

Attack Vector

An attacker who knows (or can guess) a valid username on a Keycloak realm can:

  1. Initiate a reset-credentials flow for that username via a normal unauthenticated HTTP request.
  2. Intercept or replay the subsequent requests, manipulating session state to jump past the VERIFY_EMAIL checkpoint.
  3. Submit a new password of their choosing directly to the credential update endpoint.
  4. Receive a successful UPDATE_PASSWORD event in Keycloak — without any email ever being sent or clicked.

No credentials, no prior sessions, and no victim interaction are required. The attack is entirely remote, requiring only network access to the Keycloak login endpoint.

Real-World Impact

Keycloak is typically deployed as the central authentication gate for an entire organization's application ecosystem. A successful exploit against an administrator account gives an attacker:

  • Full control of the Keycloak admin console
  • The ability to create new accounts, modify realm settings, and disable multi-factor authentication
  • Access to every downstream application protected by that Keycloak instance
  • The ability to extract identity tokens for impersonating any user

A PoC exploit has been discovered and is circulating in researcher communities (tracked via @ptdbugs on X/Twitter). Active exploitation has not been confirmed at this writing, but given the CVSS 9.1 score and the availability of exploit code, weaponization is likely imminent.


2. Who Is Affected?

Component Vulnerable Versions Fixed Version
Upstream Keycloak All versions < 26.7.2 26.7.2
Red Hat build of Keycloak < 26.4.15 26.4.15
Red Hat build of Keycloak < 26.6.6 26.6.6

Any Keycloak deployment that:

  • Exposes the login or account console to untrusted networks (including the public internet)
  • Has the default reset-credentials authentication flow enabled for any realm
  • Has not yet applied the August 19, 2026 patch

Organizations using managed identity providers (Auth0, Okta, Azure AD, Google Identity) are not affected. Organizations that self-host Keycloak or use the Red Hat build of Keycloak are affected regardless of realm configuration, because the vulnerable code path exists in the core keycloak-services module.


3. How to Detect It (Testing)

Manual Testing Steps

Step 1 — Check your Keycloak version Log in to the Keycloak admin console → Help → Server Info → Version. If the version is below 26.7.2 (upstream) or 26.4.15/26.6.6 (Red Hat build), you are vulnerable.

Step 2 — Review recent audit logs for suspicious reset patterns Navigate to: Admin Console → Realm → Events → Event Log Filter by event type: UPDATE_PASSWORD For each UPDATE_PASSWORD event, check whether it was preceded in the same session by a VERIFY_EMAIL or EXECUTE_ACTION_TOKEN event.

A password update with no corresponding email verification event in the same session is a strong indicator of exploitation.

Step 3 — Check for anomalous admin account resets Specifically filter for UPDATE_PASSWORD events on accounts with the realm-admin, admin, or custom admin roles. Any unexpected password reset on an admin account warrants immediate investigation.

Automated Scanning

Tool: Kudelski Security CVE-2026-18963 Hunt Script (GitHub)

  • Repository: github.com/kyos-public/keycloak-cve-2026-18963-hunt
  • Purpose: Parses Keycloak event logs to identify sessions where UPDATE_PASSWORD was not preceded by VERIFY_EMAIL
  • Command:
    git clone https://github.com/kyos-public/keycloak-cve-2026-18963-hunt
    cd keycloak-cve-2026-18963-hunt
    python3 hunt.py --realm <your-realm> --events-export events.json
    
  • Expected output: A list of suspicious session IDs and affected usernames

Tool: Nuclei (ProjectDiscovery)

  • Check the Nuclei templates repository for a CVE-2026-18963 template
  • Command: nuclei -t cves/2026/CVE-2026-18963.yaml -u https://<your-keycloak-host>
  • Expected output: [critical] [CVE-2026-18963] [http] if vulnerable

Tool: Keycloak Admin CLI (built-in)

# Export events for analysis
kcadm.sh get events --realm <realm-name> \
  --fields type,time,userId,sessionId,details \
  --format json > keycloak-events.json

# Grep for suspicious UPDATE_PASSWORD events
jq '[.[] | select(.type == "UPDATE_PASSWORD")]' keycloak-events.json

Code Review Checklist

For those maintaining custom Keycloak deployments or theme extensions:

  • Confirm ResetCredentialEmail authenticator has not been customized or forked prior to the fix
  • Verify that the reset-credentials browser flow in use matches the patched version
  • Check that no custom authenticators bypass EXECUTE_ACTION_TOKEN validation
  • Confirm no realm has disabled email verification from the reset-credentials flow entirely

4. How to Fix It (Mitigation)

Step-by-Step Remediation

Upstream Keycloak:

  1. Download Keycloak 26.7.2 from the official releases page: https://github.com/keycloak/keycloak/releases/tag/26.7.2
  2. Review the migration guide at https://www.keycloak.org/docs/latest/upgrading/ for any breaking changes between your current version and 26.7.2.
  3. Back up your database (PostgreSQL, MySQL, or embedded H2) and any custom themes/extensions before upgrading.
  4. Stop the Keycloak server:
    systemctl stop keycloak
    # or for containerized deployments:
    kubectl scale deployment keycloak --replicas=0
    
  5. Replace the Keycloak binaries with the 26.7.2 release.
  6. Run the database migration (Keycloak performs this automatically on first boot):
    bin/kc.sh start --optimized
    
  7. Verify the version in the admin console → Server Info.

Red Hat build of Keycloak:

# RHEL / Fedora
sudo dnf update rh-sso7-keycloak

# OpenShift / OCP
# Apply the updated Operator subscription or patch the image directly
oc patch deployment keycloak --patch \
  '{"spec":{"template":{"spec":{"containers":[{"name":"keycloak","image":"registry.redhat.io/rh-sso-7/sso76-openshift-rhel8:26.4.15"}]}}}}'

Immediate Workaround (If Patching Is Delayed)

If you cannot patch immediately, restrict access to the Keycloak login endpoints from untrusted networks:

# Nginx — block /realms/*/login-actions/reset-credentials from external IPs
location ~* /realms/.*/login-actions/reset-credentials {
    allow 10.0.0.0/8;       # internal network
    allow 192.168.0.0/16;
    deny all;
}
# Apache — equivalent restriction
<LocationMatch "^/realms/.*/login-actions/reset-credentials">
    Require ip 10.0.0.0/8
    Require ip 192.168.0.0/16
</LocationMatch>

⚠️ This workaround is not a fix. It reduces exposure but does not patch the vulnerability. Any attacker with internal network access can still exploit it. Patching remains mandatory.

Configuration Hardening

If your realm does not require self-service password reset (e.g., IT-managed credential resets only), disable the reset-credentials flow entirely:

  1. Admin Console → Authentication → Flows → Reset Credentials
  2. Set the top-level flow binding to None under Authentication → Bindings → Reset Credentials Flow
  3. Inform users that password resets must go through the helpdesk

5. How to Test the Fix (Validation)

Regression Test Scenarios

Scenario A — Verify the attack no longer works Attempt to reproduce the bypass sequence (manipulating session state to skip email verification) against the patched Keycloak instance. Expected result: Keycloak returns an error and does not update the credential.

Scenario B — Verify legitimate password reset still works Initiate a genuine reset-credentials flow for a test user. Receive the verification email, click the link, and set a new password. Expected result: Workflow completes successfully end-to-end.

Scenario C — Verify no regression in admin console access Log in as an admin user. Confirm all realm management functions are accessible. Expected result: No functionality degraded.

Security Test Cases

Test Case 1: Bypass Attempt Fails on Patched Instance

  • Precondition: Keycloak 26.7.2 is deployed
  • Steps: Execute the CVE-2026-18963 bypass sequence (skip VERIFY_EMAIL step)
  • Expected Result: HTTP 400 or redirect to error page; UPDATE_PASSWORD event does NOT appear in logs

Test Case 2: Legitimate Reset Flow Succeeds

  • Precondition: Valid test user account exists; email is configured
  • Steps: Initiate reset, receive email, click token link, set new password
  • Expected Result: SEND_RESET_PASSWORDVERIFY_EMAIL / EXECUTE_ACTION_TOKENUPDATE_PASSWORD all appear in event log in sequence

Automated Validation Test

import requests

KEYCLOAK_BASE = "https://your-keycloak.example.com"
REALM = "your-realm"
TARGET_USERNAME = "test-user-for-pentest"

def attempt_bypass():
    session = requests.Session()
    
    # Step 1: Get the login page to establish session
    r = session.get(f"{KEYCLOAK_BASE}/realms/{REALM}/protocol/openid-connect/auth"
                    f"?client_id=account&response_type=code"
                    f"&redirect_uri={KEYCLOAK_BASE}/realms/{REALM}/account/")
    
    # Step 2: Navigate to reset credentials
    reset_url = f"{KEYCLOAK_BASE}/realms/{REALM}/login-actions/reset-credentials"
    r = session.get(reset_url)
    
    # Step 3: Submit username to initiate reset
    action_url = r.url  # contains the session_code
    r = session.post(action_url, data={"username": TARGET_USERNAME})
    
    # Step 4: Attempt to skip verification — replay/manipulate the flow
    # If vulnerable, the next step would allow password update without token
    # Patched systems should return an error or redirect to login
    
    if "updatePassword" in r.url or r.status_code == 200 and "password" in r.text.lower():
        print(f"[VULNERABLE] Password reset bypass succeeded for: {TARGET_USERNAME}")
        return True
    else:
        print(f"[PATCHED] Bypass was blocked. Status: {r.status_code}")
        return False

attempt_bypass()

6. Prevention & Hardening

Best Practices

Practice 1: Keep Keycloak on the latest release Keycloak is under active development and security patches are released frequently. Subscribe to the Keycloak security advisories mailing list and the Red Hat security advisories RSS feed to receive notifications immediately.

Practice 2: Restrict the reset-credentials endpoint to known networks Unless your users must reset their own passwords from arbitrary external IPs, consider placing the Keycloak login UI behind a VPN or internal-only DNS resolution. This does not eliminate the attack surface for insider threats but significantly narrows the blast radius.

Practice 3: Enable MFA on all privileged accounts Even if credentials are reset via a bypass, MFA (TOTP, WebAuthn, or hardware keys) configured as a required step in the browser flow will prevent attackers from completing authentication. Admin realm accounts especially should enforce MFA unconditionally.

Practice 4: Audit the custom flow and authenticator inventory If your organization has implemented custom authenticators or modified the built-in flows, review those modifications for similar state-management anti-patterns. The reset-credentials flow bypass described here is one manifestation of a broader design weakness in flows that track state without cryptographic binding.

Practice 5: Implement network segmentation Do not expose the Keycloak admin console (/auth/admin or /admin) to the public internet under any circumstances. The admin API should be accessible only from management networks or bastion hosts.

Monitoring & Detection

Enable full event logging in Keycloak and forward events to your SIEM in real time:

  1. Admin Console → Events → Config → Enable saving of user events
  2. Enable event types: UPDATE_PASSWORD, LOGIN_ERROR, RESET_PASSWORD, EXECUTE_ACTION_TOKEN, SEND_RESET_PASSWORD, VERIFY_EMAIL
  3. Set event expiry to at least 90 days for forensic retention

SIEM detection rule (Splunk example):

index=keycloak sourcetype=keycloak:events
| where type="UPDATE_PASSWORD"
| join sessionId [
    search index=keycloak sourcetype=keycloak:events
    | where type IN ("VERIFY_EMAIL", "EXECUTE_ACTION_TOKEN")
    | table sessionId
]
| where isnull(sessionId)
| table _time, userId, sessionId, ipAddress, realmId
| sort -_time

This rule alerts on any UPDATE_PASSWORD event that has no matching email verification event for the same session — the forensic signature of successful exploitation.


References

Latest from the blog

See all →