CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-1529
8.10.02%

Keycloak Unlocked: Bypassing Org Security with CVE-2026-1529

Alon Barad
Alon Barad
Software Engineer

Feb 17, 2026·6 min read·7 visits

PoC Available

Executive Summary (TL;DR)

Keycloak forgot to verify JWT signatures in the organization invitation flow. Attackers can take a valid invite token, change the organization ID in the payload to whatever they want, and self-register into restricted organizations without a valid key. It's a high-severity bypass (CVSS 8.1) affecting versions prior to late January 2026.

A critical lapse in cryptographic hygiene within Keycloak's 'Organizations' feature allows attackers to forge invitation tokens. By neglecting to verify the digital signature of JSON Web Tokens (JWTs), Keycloak inadvertently permitted anyone with a valid invite to modify the payload—swapping organization IDs and email addresses—to gain unauthorized access to restricted tenants.

The Hook: Trust, But Don't Verify

Keycloak is the behemoth of the open-source Identity and Access Management (IAM) world. It’s the gatekeeper we trust to hold the keys to the kingdom, handling everything from OAuth flows to user federation. Recently, Keycloak introduced a shiny new feature called Organizations, designed to support multi-tenancy and B2B SaaS scenarios. It allows admins to invite users to specific organizations via email links containing a token.

But here's the kicker: for a brief, terrifying window in versions 26.x, the gatekeeper stopped checking IDs. When processing these invitation tokens, the system assumed that if a token looked like a JWT, it must be valid. It didn't bother checking the cryptographic signature—the wax seal that proves the letter wasn't tampered with.

This isn't just a minor bug; it's a fundamental breakdown of the JWT trust model. In the security world, we call this "signature exclusion" or "algorithm confusion's" dumber cousin: simply ignoring the signature entirely. It turned Keycloak's robust security model into a purely advisory suggestion, allowing anyone with a text editor to rewrite their own access permissions.

The Flaw: A Failure of Logic

To understand why this is hilarious (in a dark way), you have to understand how Keycloak handles tokens. Usually, the code is paranoid. It checks expiration, issuers, audiences, and crucially, the cryptographic signature using the realm's public key. If a single bit is out of place, the token is rejected.

However, in the org.keycloak.organization.utils.Organizations class, the developers got a little lazy—or perhaps just distracted. The method parseInvitationToken was tasked with reading the token from the URL query parameters. Instead of invoking the full verification pipeline, the code simply deserialized the Base64-encoded payload directly into a Java object.

It’s the digital equivalent of a bouncer looking at a driver's license, seeing that it's a rectangular piece of plastic with a photo, and letting you in—without noticing that the name is written in Crayon and the birth year is 3025. Because the signature verification step (verifier.verify()) was completely omitted, the server accepted any JSON blob formatted as a token, regardless of who signed it (or if it was signed at all).

The Code: The Smoking Gun

Let's look at the crime scene. The vulnerable code resided in org.keycloak.organization.utils.Organizations.java. Here is the logic that essentially rolled out the red carpet for attackers:

// THE VULNERABLE CODE
public static InviteOrgActionToken parseInvitationToken(HttpRequest request) throws VerificationException {
    // ... query param extraction ...
    String tokenFromQuery = queryParameters.getFirst(Constants.TOKEN);
 
    // LOOK HERE: create() parses the text, getToken() returns the object.
    // There is NO .verify() call. There is NO signature check.
    return TokenVerifier.create(tokenFromQuery, InviteOrgActionToken.class).getToken();
}

The fix, introduced in commit 8fc9a98026106a326f4faa98d4c9a48341ace2d7, is a lesson in how verbose Java security can get. They had to wire in the KeycloakSession, fetch the SignatureVerifierContext, and explicitly force the check:

// THE PATCHED CODE
public static InviteOrgActionToken parseInvitationToken(KeycloakSession session, HttpRequest request) throws VerificationException {
    // ... setup ...
    TokenVerifier<InviteOrgActionToken> verifier = TokenVerifier.create(tokenFromQuery, InviteOrgActionToken.class)
            .withChecks(TokenVerifier.IS_ACTIVE, /* URL checks */);
 
    // Fetch the realm's keys to verify the signature
    SignatureVerifierContext verifierContext = session.getProvider(SignatureProvider.class, 
            verifier.getHeader().getAlgorithm().name())
            .verifier(verifier.getHeader().getKeyId());
 
    verifier.verifierContext(verifierContext);
    
    // The magic word: .verify()
    return verifier.verify().getToken(); 
}

The difference is subtle in lines of code but infinite in security implications. The first version trusts the input; the second version treats the input like a hostile combatant until proven otherwise.

The Exploit: Forging Your Way In

Exploiting this requires zero advanced hacking tools. You don't need heap spraying or ROP chains; you just need a browser developer console or a simple Python script. The attack vector relies on the fact that a JWT is just Header.Payload.Signature. Since the server ignores the Signature, we can change the Payload and leave the Signature as garbage (or keep the original, it doesn't matter).

Step 1: The Setup. The attacker needs a valid invitation link. They can invite themselves to a "dummy" organization they control to get a valid token format. The link looks like https://auth.target.com/realms/main/protocol/openid-connect/registrations?token=eyJhbG...

Step 2: The Tampering. The attacker takes the token string. The middle part (between the two periods) is the Base64-encoded payload. They decode it and see JSON:

{
  "iss": "https://auth.target.com/realms/main",
  "orgId": "b-123-useless-org",
  "email": "attacker@evil.com",
  "exp": 1790000000
}

They change "orgId" to the ID of the Executive Org (e.g., "a-999-super-secret-admin-org") which they might have enumerated via other API leaks or guessed. They ensure the email matches the account they want to register.

Step 3: The Delivery. The attacker re-encodes this JSON to Base64 and pastes it back into the token string. They send the request. Keycloak's parseInvitationToken method deserializes the forged payload, sees the target orgId, assumes it's valid because it deserialized correctly, and grants the attacker membership to the target organization. Congratulations, you are now an employee.

The Impact: Breaking Tenant Isolation

The impact here is a complete violation of multi-tenancy. In a SaaS platform using Keycloak Organizations, this vulnerability allows cross-tenant access. An attacker can move laterally from a low-value demo organization into a high-value corporate organization simply by knowing the target's ID.

Depending on how the application consumes these organizational memberships, this could lead to:

  1. Data Exfiltration: Accessing shared documents, proprietary data, or user lists belonging to the victim organization.
  2. Privilege Escalation: If the invitation flow assigns default roles (like 'Member' or 'Admin') automatically, the attacker gains those privileges immediately upon registration.
  3. Social Engineering: Once inside the org, the attacker looks like a legitimate user, making phishing attacks against other employees significantly more effective.

This scores an 8.1 on CVSS not because it crashes the server, but because it destroys the integrity of the access control model. Confidentiality and Integrity are both rated 'High' for a reason.

The Fix: Patch or Die

Red Hat and the Keycloak maintainers pushed a fix in late January 2026. The remediation is straightforward: Update Keycloak immediately.

If you are running Keycloak version 26.2.x, upgrade to 26.2.13-1 or later. If you are running version 26.4.x, upgrade to 26.4.9-1 or later.

If patching is currently impossible due to bureaucratic inertia or change freezes, there is a configuration workaround: Disable the Organizations feature. This feature is often guarded by a feature flag. Turning it off removes the vulnerable endpoint entirely. However, if your business logic relies on this feature, you are effectively stuck between a rock and a hard place until you patch.

Official Patches

Red HatRHSA-2026:2363 - Keycloak Security Update
KeycloakOfficial GitHub Commit

Fix Analysis (1)

Technical Appendix

CVSS Score
8.1/ 10
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N
EPSS Probability
0.02%
Top 97% most exploited

Affected Systems

Keycloak 26.2.x prior to 26.2.13-1Keycloak 26.4.x prior to 26.4.9-1Red Hat build of Keycloak (RHBK)

Affected Versions Detail

Product
Affected Versions
Fixed Version
Keycloak
Red Hat
26.2.0 - 26.2.1226.2.13-1
Keycloak
Red Hat
26.4.0 - 26.4.826.4.9-1
AttributeDetail
CWE IDCWE-347 (Improper Verification of Cryptographic Signature)
CVSS v3.18.1 (High)
Attack VectorNetwork (AV:N)
Privileges RequiredLow (PR:L)
Exploit StatusPoC Available
EPSS Score0.00016 (Rising)
ImpactHigh Integrity & Confidentiality Loss

MITRE ATT&CK Mapping

T1566Phishing
Initial Access
T1098Account Manipulation
Persistence
T1078Valid Accounts
Defense Evasion
CWE-347
Improper Verification of Cryptographic Signature

The product does not verify, or incorrectly verifies, the cryptographic signature for data, allowing the data to be modified without detection.

Known Exploits & Detection

GitHubPython script for modifying JWT claims in Keycloak invitation tokens
GitHubRegistration endpoint bypass tool
NucleiDetection Template Available

Vulnerability Timeline

Fix committed by Stian Thorgersen
2026-01-29
Public disclosure and Red Hat Security Advisories published
2026-02-09
First PoC released on GitHub
2026-02-12

References & Sources

  • [1]Red Hat CVE Database
  • [2]Bugzilla Report #2433783

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.