CVE-2026-5430: WSO2 JWT Bypass, PoC Status and Detection. CVE-2026-5430 lets forged JWTs past WSO2 API Manager auth. See affected versions, public PoC status, how to detect exploitation and test your Keycloak APIs.
CVE-2026-5430 is a CVSS 10.0 authentication bypass in WSO2 API Manager and related products: JWTs signed with an unsupported algorithm were logged as errors but not rejected, so forged tokens reached admin REST APIs. It is in CISA’s Known Exploited Vulnerabilities (KEV) catalog, so patch to WSO2’s fixed update levels, listed below. The advisory and the CVE record list only WSO2 products, not Keycloak.
This post answers what people search this CVE for: whether your version is exposed, how the bypass works, whether a public proof of concept (PoC) exists, and how to look for signs that you were hit. The second half is for teams with Keycloak in the picture, with a safe test that shows whether your own APIs reject a token whose algorithm was switched.
Key takeaways
- Exposed: WSO2 API Manager 4.1.0 to 4.6.0, and API Control Plane, Traffic Manager and Universal Gateway 4.5.0 and 4.6.0, below the update levels in WSO2’s advisory.
- Public PoC: Greenbone reported on 30 September 2026 that a technical analysis with a PoC exploit is publicly available, although we have not seen a full public exploit write-up ourselves. This post explains the mechanics and detection, with no working payload.
- Detection: search WSO2’s carbon logs for
Authentication FailureandPublic key is not RSA, then match those times against HTTP 200 responses from the admin REST APIs.- Keycloak: not listed in the advisory, but WSO2 can hold the secret of a Keycloak client with the
adminrole, so a compromised WSO2 can lead to your realm.
Which WSO2 versions does CVE-2026-5430 affect?
WSO2’s advisory WSO2-2026-5328 lists four products, and you are exposed if you run one of these versions below its fixed U2 update level (U2 is WSO2’s update system for support subscribers):
| Product | Affected versions | Fixed update level |
|---|---|---|
| WSO2 API Manager | 4.1.0 to 4.6.0 | 4.6.0 U21, 4.5.0 U57, 4.4.0 U72, 4.3.0 U108, 4.2.0 U197, 4.1.0 U257 |
| WSO2 API Control Plane | 4.5.0, 4.6.0 | 4.6.0 U22, 4.5.0 U58 |
| WSO2 Traffic Manager | 4.5.0, 4.6.0 | 4.6.0 U21, 4.5.0 U56 |
| WSO2 Universal Gateway | 4.5.0, 4.6.0 | 4.6.0 U21, 4.5.0 U57 |
If you build the open-source code without a subscription, the fix is wso2/carbon-apimgt#13752, and the advisory also lists a test change, wso2/product-apim#14167. The advisory rates the flaw 10.0 by default and 9.8 in single-tenant deployments. It offers no configuration workaround: you patch or, if you cannot, migrate to an unaffected version. Beazley Security’s advisory suggests restricting internet-facing management consoles and gateways to trusted administrative networks until you have patched, which reduces exposure but does not remove the flaw.
A dependency scanner may raise this CVE against a WSO2 library rather than a product, so check what it matched against the NVD entry and the advisory’s table above.
When was CVE-2026-5430 disclosed, patched and exploited?
The fix was public for five months before the first publicly reported exploitation attempts.
| Date (2026) | Event | Source |
|---|---|---|
| 12 April | Code fix merged | carbon-apimgt#13752 |
| 3 May | WSO2 publishes its advisory | WSO2-2026-5328 |
| 6 August | CVE record published | CVE record |
| 13 September | First exploitation attempt on watchTowr’s honeypots | SecurityWeek |
| 24 September | Added to KEV, with a federal due date of 27 September | CISA KEV data |
| 30 September | Public PoC reported | Greenbone |
If you read the KEV entry directly, you will notice that its text does not match the bug. In the KEV data (catalog version 2026.11.03), the entry’s name is “WSO2 Multiple Products Path Traversal Vulnerability”, and its description says the products “contain a path traversal vulnerability that could allow for unrestricted file upload and lead to remote code execution.” The same entry lists CWE-347, Improper Verification of Cryptographic Signature, and links to WSO2’s authentication bypass advisory. It looks like a copy error in the catalog rather than a second bug, but that is our reading and not something CISA has said, so treat a compromised host as if either description could be true. WSO2’s update levels are the only fix on offer in both cases.
How does the CVE-2026-5430 exploit work?
The fix in pull request #13752 shows the mechanism, and it needs no cryptographic trick. WSO2’s signature check, JWTUtil.verifyTokenSignature, only handles RS256, RS384 and RS512, and it throws an exception for any other algorithm in the token’s header, with the slightly misleading message Public key is not RSA. The OAuthAuthenticationInterceptor in front of WSO2’s own management REST APIs caught that exception, logged Authentication Failure and returned, so the request kept moving through the processing chain. A second catch block in the same method logged an error and fell through in the same way.
A token with an unsupported algorithm makes the signature check throw (1, 2) and the interceptor logs the error (3). Before the fix the interceptor returned and the request carried on, and after the fix it throws an error that becomes an HTTP response.
Greenbone’s analysis describes the result as fail open, meaning an error leaves access granted rather than denied: the exception is logged, “but no failed authentication state is set, allowing full access to the REST API.” An attacker needs no key, because the signature is never successfully checked and nothing rejects the token. That explains why the tokens on watchTowr’s honeypots arrived with administrator privileges already written into them, and why watchTowr’s Yordan Ganchev told SecurityWeek that a forged token “yields access to every API backend endpoint and its credentials, consumer keys and secrets for every registered application.”
The fix changes both catch blocks to throw an exception that GlobalThrowableMapper turns into an error response. WSO2’s companion test then checks that an invalid JWT is answered with a 401. We describe the mechanism at this level on purpose, and we leave out the token contents and request details that would turn it into a recipe.
Is CVE-2026-5430 a JWT algorithm confusion attack?
It is in the same family, but it is not the classic attack. RFC 8725 section 2.1 describes the two textbook forms: setting alg to none so no signature is checked, and switching RS256 to HS256 so a library uses the RSA public key as an HMAC secret. Our guide to algorithm confusion and the none algorithm walks through both. In this CVE, WSO2’s verifier did refuse the algorithm, and the error handling around it failed to act on the refusal. A verifier can have a correct list of algorithms and still be bypassed if an error in that path is logged and then ignored.
Is there a public PoC for CVE-2026-5430?
Yes. Greenbone’s post of 30 September 2026 says “a detailed technical analysis with proof-of-concept (PoC) exploit is publicly available”. We have not seen a full public exploit write-up ourselves, and earlier coverage said none existed: Beazley Security’s advisory said that “Full technical write-ups and a public proof-of-concept for this WSO2 flaw were not available at the time of publication”, and on 16 September SecurityWeek reported that technical details did not appear to be public, while noting that watchTowr “easily reproduced the vulnerability based on the vendor’s patch.” So the bug could be worked out from the public fix well before any PoC was published.
On GitHub, searching the CVE number also turns up repositories that describe themselves as lab reproductions and as detection scripts. We read some of their READMEs but did not run or audit the code, and we do not link them here. If your team wants to use one, treat it as untrusted code, keep it in an isolated lab, and remember that a “detection” script still sends forged tokens to its target, so run it only against systems you are authorized to test. You should not need one to answer the main question, because the update level tells you whether you are exposed and the test later in this post checks your own verifiers.
Does CVE-2026-5430 affect Keycloak?
Keycloak is not among the products that WSO2’s advisory and the CVE record list. Keycloak is the authorization server that signs tokens, and this CVE is a flaw in the WSO2 code that verifies them.
It still matters to Keycloak users because WSO2 API Manager is often deployed alongside it. In WSO2’s Keycloak key manager setup, Keycloak issues the tokens for your APIs, you give WSO2 the client ID and client secret of a Keycloak client, and the guide tells you to assign the admin role in that client’s service account roles. An attacker who gets into WSO2’s admin plane may therefore be able to reach a credential with wide powers over your realm, and a well-configured realm does not prevent that. Check which role your key-manager client has, because it sets how far this incident can reach.
The CVE’s other lesson applies to any API that accepts Keycloak tokens: every resource server (the API that receives the token) has to do its own checks correctly, and an error in those checks must end the request. Our guide to verifying a Keycloak-issued access token on the backend covers this end to end.
How do you detect CVE-2026-5430 exploitation?
Rescana noted on 28 September that WSO2, CISA and NVD publish no classic indicators such as IP addresses, file hashes or token fingerprints, so you are looking for behavior. These are the places to search:
| Where | What to look for | What it means |
|---|---|---|
Carbon logs (repository/logs/wso2carbon*) |
Authentication Failure with Public key is not RSA |
In a vulnerable build, the fix’s diff shows this was written for a request that then continued |
| Carbon logs | Error while authenticating incoming request to API Manager REST API |
The second catch block, which also fell through before the fix; expect more noise here |
| Carbon logs on a patched build | Public key is not RSA for alias |
The new log line: the attempt happened and the build rejected it |
repository/logs/http_access_*.log |
HTTP 200 for /api/am/admin/, /api/am/publisher/ or /api/am/devportal/ at the same times |
Beazley Security’s hunting advice: an authenticated answer with no matching login |
| WSO2 admin data | New or newly privileged admins, changed APIs, routing or access policies | Also from Beazley: what an attacker does after getting in |
| Keycloak admin events | Changes made by the key-manager service account that you cannot explain | The stolen credential being used against your realm |
A carbon log match on its own shows that such a token arrived, so match its timestamp against the access log to see whether the request succeeded. If a reverse proxy in front of WSO2 records bearer tokens, you can also decode the JWT header of those requests and look for an alg other than RS256, RS384 or RS512. Our JWT Decoder reads the header of a sample token.
Three caveats affect how much a clean result proves:
- Search further back than 13 September. That is the first attempt watchTowr saw on its honeypots, so it does not rule out earlier use against real deployments, and the fix had been public since April.
- Check that your logs still exist. WSO2’s log guide says rollover is time-based by default, with a default interval of one day, and any retention or cleanup you configured may have removed the period you care about.
- Check that Keycloak was saving events. Keycloak admin events only help if your realm was set to save them, which the Keycloak Server Administration Guide covers under auditing admin events. If saving was off, you may only have your server logs. Our Keycloak auditing and event logging guide covers the setup, and it is worth doing before the next incident. On Skycloak, audit logs cover logins, failures and admin actions, with export to your SIEM.
What should you do if an affected WSO2 deployment was exposed?
If you ran an affected version on a network an attacker could reach, assume the admin plane may have been accessed, whatever the logs show, and work through these steps:
- Patch first, to the update level in the table above, or apply the community pull requests if you build from source.
- Rotate what WSO2 holds. Given what watchTowr says a forged token exposes, rotate consumer keys and secrets and your API backend credentials.
- Rotate the Keycloak key-manager secret. Open the client’s Credentials tab in the Keycloak admin console and regenerate the secret, then update the key manager entry in WSO2. While you are there, reduce the service account’s roles if your setup works with less than
admin, and test that first. - End sessions, and know the limit of that. The realm’s Sessions page can sign out all active sessions, but the Server Administration Guide notes that this “does not revoke outstanding access tokens”, which “must expire naturally”, so plan for access tokens that were already issued to keep working until then. Our guide to JWT lifecycle management explains how expiry and revocation interact.
- Search for the indicators above, and keep a copy of the logs before they roll over.
- Follow CISA’s triage requirement if you are a US federal agency, since the KEV entry marks forensic triage as required alongside mitigation.
Patched on the day, not on your next maintenance window
Keycloak 26.7.2 fixed CVE-2026-18963, an account takeover through password reset. Skycloak had it available for auto-upgrade and told customers the same day upstream shipped it. Self-hosted teams schedule that work themselves.
How do you test that an API rejects algorithm switching?
Send your own API a real token with its header changed and confirm the answer is a 401. This script needs Node 18 or newer and no packages. Give it a short-lived token for a low-privilege test user, and run it only against a test environment you own or are authorized to test. The token’s claims stay as Keycloak issued them, so a failed check shows that verification is broken without granting the test any extra privileges.
// fail-closed-test.mjs
// API_URL=https://staging.example.com/orders TEST_TOKEN=... node fail-closed-test.mjs
const { API_URL, TEST_TOKEN } = process.env;
const [header, payload, signature] = TEST_TOKEN.split('.');
const decoded = JSON.parse(Buffer.from(header, 'base64url'));
const encode = (obj) => Buffer.from(JSON.stringify(obj)).toString('base64url');
const reversed = [...signature].reverse().join('');
const cases = [
['control: the untouched token, expect 200', TEST_TOKEN],
['alg switched to HS256, expect 401', `${encode({ ...decoded, alg: 'HS256' })}.${payload}.${signature}`],
['alg switched to none, expect 401', `${encode({ ...decoded, alg: 'none' })}.${payload}.`],
['unknown kid, expect 401', `${encode({ ...decoded, kid: 'not-in-jwks' })}.${payload}.${signature}`],
['changed signature, expect 401', `${header}.${payload}.${reversed}`],
];
for (const [name, token] of cases) {
const res = await fetch(API_URL, { headers: { authorization: `Bearer ${token}` } });
console.log(res.status, name);
}
A correct verifier, such as the jose example below, should answer 200 for the control and 401 for the other four. A 200 for either algorithm switch is the failure you are testing for, the kind a log-and-continue catch block like the one in this CVE produces. Treat a 500 as a failure to investigate too, and check that the request did not reach your backend. If the control does not return 200, your token or URL is wrong and the other results mean nothing.
How should a resource server verify Keycloak tokens?
RFC 8725 section 3.1 says libraries “MUST enable the caller to specify a supported set of algorithms and MUST NOT use any other algorithms when performing cryptographic operations.” For an API that trusts Keycloak tokens, that gives you this checklist:
- Allow-list the algorithm. Check which algorithm your realm signs with, which the Server Administration Guide lists as the Default Signature Algorithm setting on the realm’s Tokens tab. Accept only the one your realm uses, and never let the token’s
algheader choose the verification method. - Take keys only from your realm’s JWKS, at a URL like
https://auth.example.com/realms/acme/protocol/openid-connect/certs, select the key bykid, and reject akidthat is not in the set. Our explainer on JSON Web Key Sets covers caching and rotation, and the JWKS Verifier confirms akidresolves. - Check
issexactly, with no wildcard matching and no tolerance for trailing slash differences. - Check
audagainst your API’s own identifier, as RFC 8725 section 3.9 asks. A related flaw, Apache CXF CVE-2026-50627, skipped this check, and our post on MCP servers returning 401 on audience shows how the check looks when it works. - Check
expandnbfwith a small clock skew allowance. - Fail closed. Any exception during parsing, key lookup or signature checking must end in a 401, never in a log line followed by the next middleware.
Node.js with jose
The jose library takes the algorithm list, issuer and audience as options, and jwtVerify throws on any failure. Set algorithms yourself, because its documented default is “all algorithms applicable to the key or secret”:
import { createRemoteJWKSet, jwtVerify } from 'jose';
const issuer = 'https://auth.example.com/realms/acme';
const JWKS = createRemoteJWKSet(new URL(`${issuer}/protocol/openid-connect/certs`));
export async function requireToken(req, res, next) {
try {
const token = (req.headers.authorization || '').replace(/^Bearer /, '');
const { payload } = await jwtVerify(token, JWKS, {
issuer,
audience: 'orders-api',
algorithms: ['RS256'],
});
req.auth = payload;
return next();
} catch (err) {
// Every failure path ends here, and every one returns 401.
return res.status(401).json({ error: 'invalid_token' });
}
}
Spring Boot resource server
Spring Security’s NimbusJwtDecoder lets you pin the algorithm when you build it, and the default validator checks exp and nbf. Add issuer and audience validators on top:
@Bean
JwtDecoder jwtDecoder() {
String issuer = "https://auth.example.com/realms/acme";
NimbusJwtDecoder decoder = NimbusJwtDecoder
.withJwkSetUri(issuer + "/protocol/openid-connect/certs")
.jwsAlgorithm(SignatureAlgorithm.RS256)
.build();
OAuth2TokenValidator<Jwt> audience = new JwtClaimValidator<List<String>>(
JwtClaimNames.AUD, aud -> aud != null && aud.contains("orders-api"));
decoder.setJwtValidator(new DelegatingOAuth2TokenValidator<>(
JwtValidators.createDefaultWithIssuer(issuer), audience));
return decoder;
}
Python with PyJWT
PyJWT requires the algorithms argument on decode, which is the protection RFC 8725 asks for:
import jwt
from jwt import PyJWKClient
ISSUER = "https://auth.example.com/realms/acme"
jwks = PyJWKClient(f"{ISSUER}/protocol/openid-connect/certs")
def verify(token: str) -> dict:
key = jwks.get_signing_key_from_jwt(token).key
return jwt.decode(
token,
key,
algorithms=["RS256"],
audience="orders-api",
issuer=ISSUER,
) # raises on any failure; the caller must turn that into a 401
What should you check in an API gateway’s JWT validation?
A gateway sits in front of many APIs, so a mistake in its JWT handling affects all of them. Whether you run WSO2, Kong, NGINX, Envoy or a cloud API gateway, point the test script above at it, and check that the configuration names the accepted algorithms explicitly and that the gateway checks issuer and audience as well as your backends. Keep your patching current too, because this fix was public for five months before the first reported attempts. Our comparison of token introspection and local validation and our guide to API authentication best practices cover where gateway checks end and service checks begin.
How do you set up Keycloak so verifier mistakes hurt less?
Keycloak cannot fix a broken verifier, but these standard Keycloak 26.x settings reduce the damage one can do:
- Keep one signing algorithm per realm. Clients can override the realm’s default, and mixed algorithms make allow-lists harder to write, so override only when a client needs it.
- Keep access tokens short-lived. A short access token lifespan limits how long a stolen real token stays useful, although it does nothing against a forged token that a broken verifier accepts.
- Give every API its own audience. Check that the
audof the tokens your API receives names that API, and not only another client of the realm. Our post on Keycloak token validation for APIs shows the audience mapper setup, and it stops a token issued for one internal tool from working on every API that trusts the realm. - Rotate keys with overlap. Add a new key provider with a higher priority, keep the old key available until the tokens it signed have expired, and only then disable it.
- Keep token kinds apart with the
typclaim. The decoded Keycloak access token in our JWT validation tutorial carries"typ": "Bearer". Accept only the kind of token your API expects and reject other kinds, such as ID tokens, which follows RFC 8725 section 3.12 on separate validation rules for different kinds of JWT.
Frequently Asked Questions
What is CVE-2026-5430?
CVE-2026-5430 is an authentication bypass, rated CVSS 10.0 by WSO2, in WSO2 API Manager, API Control Plane, Traffic Manager and Universal Gateway. A JWT signed with an unsupported algorithm could get past authentication, which can lead to administrative account takeover. CISA added it to the KEV catalog on 24 September 2026.
Is there a working exploit for CVE-2026-5430?
Yes. watchTowr’s honeypots saw attempts from 13 September 2026, and Greenbone reports that a PoC exploit is public. Patch now and do not wait for a scanner to confirm it.
Is Keycloak vulnerable to CVE-2026-5430?
Keycloak is not listed: WSO2’s advisory names only WSO2 products, and the flaw is in WSO2’s token verification. Keycloak deployments are only exposed indirectly: an attacker who takes over an unpatched WSO2 admin plane may reach the Keycloak client credentials WSO2 holds when Keycloak is its key manager. Patching WSO2 and rotating those credentials closes that gap.
What is a JWT algorithm confusion attack?
It is a class of attacks, described in RFC 8725 section 2.1, where the verifier lets the token’s alg header decide how to check the signature. The classic forms are alg: none, which skips verification, and switching RS256 to HS256 so the public key is used as an HMAC secret. Allow-listing algorithms on the verifier prevents both.
Which algorithm should I allow for Keycloak access tokens?
Allow exactly the algorithm your realm signs with, as set in its Default Signature Algorithm. If you moved the realm to ES256 or another algorithm, allow that one instead. Avoid accepting everything a library supports, because RFC 8725 section 3.1 asks for a fixed set chosen by the caller.
Does a short access token lifespan protect against CVE-2026-5430?
Not directly. A short lifespan limits how long a stolen genuine token works, but a forged token accepted by a broken verifier was never issued by Keycloak, so its lifespan is whatever the attacker writes. Short lifespans still help with the secondary risk of leaked credentials after a WSO2 compromise.
What to do next
Patch WSO2 to the fixed update level for your version, because this CVE is on the KEV list and a PoC is public. Then search your logs for the indicators above, and rotate the Keycloak key-manager client secret if the deployment was exposed. After that, run the fail-closed test against every API that accepts Keycloak tokens, and fix any verifier that returns anything but a 401. Our JWT best practices for developers guide is a useful companion for that review.
Your verifiers stay your responsibility wherever Keycloak runs, but running Keycloak itself does not have to be: Skycloak’s managed hosting runs upstream Keycloak and takes upgrades and operations off your team.
Sources
- WSO2, Security Advisory WSO2-2026-5328, published 2026-05-03, retrieved 2026-11-04
- CVE Program, CVE-2026-5430 record, published 2026-08-06, retrieved 2026-11-04
- NVD, CVE-2026-5430
- WSO2, carbon-apimgt pull request #13752, “Improve exception handling”, merged 2026-04-12, retrieved 2026-11-04
- WSO2, product-apim pull request #14167, “Improve advanced configuration tests”, merged 2026-04-22, retrieved 2026-11-04
- CISA, Known Exploited Vulnerabilities catalog and its catalog data (version 2026.11.03), retrieved 2026-11-04
- SecurityWeek, Enterprises Warned of Attacks Exploiting WSO2 Vulnerability, 2026-09-16, retrieved 2026-11-04
- The Hacker News, article on active exploitation attempts, 2026-09-16, retrieved 2026-11-04
- Greenbone, WSO2 API Manager JWT Bypass Now Under Active Attack, 2026-09-30, retrieved 2026-11-04
- Beazley Security, Critical Authentication Bypass in WSO2 API Management Products Under Active Exploitation, retrieved 2026-11-04
- Rescana, WSO2 API Manager CVE-2026-5430, 2026-09-28, retrieved 2026-11-04
- IETF, RFC 8725, JSON Web Token Best Current Practices, February 2020
- WSO2, Configure Keycloak as a Key Manager and Managing Log Growth, retrieved 2026-11-04
- Keycloak, Server Administration Guide, retrieved 2026-11-04
- panva, jose and its JWTVerifyOptions documentation, retrieved 2026-11-04



