Like slipping through a badge reader only when two doors misfire at the same instant
CVE-2026-5516 is an IBM WebSphere Application Server Liberty security-bypass flaw in environments running versions 22.0.0.11 through 26.0.0.5 *and* using the appSecurity-3.0, appSecurity-4.0, or appSecurity-5.0 feature. IBM says a remote attacker can bypass security only under *limited conditions* by exploiting a specific timing window, and the published CVSS vector already tells the important part: it requires high privileges and high attack complexity while impacting confidentiality only.
IBM's MEDIUM 4.4 baseline is fair in the abstract, but in real enterprise operations this lands lower because the exploit chain is stacked with friction: the attacker must already have authenticated, high-privileged access to the target application path, hit a race condition reliably, and land on a Liberty deployment with the relevant security feature enabled. That is post-initial-access behavior against a narrower subset of Liberty estates, with no public exploitation evidence, no KEV listing, and a very low EPSS.
4 steps from start to impact.
Get into a privileged Liberty-backed workflow
Burp Suite for session handling and request replay after credential theft, not an unauthenticated internet exploit.- Reachable Liberty application endpoint
- Valid authenticated account with high privileges
- Ability to interact with the affected application path remotely
- This is not unauthenticated remote code execution
- MFA, SSO conditional access, PAM, and admin segregation reduce reachable targets
- Many Liberty deployments are internal app tiers, not internet-edge services
Land on the right Liberty feature set
22.0.0.11 through 26.0.0.5 with appSecurity-3.0, appSecurity-4.0, or appSecurity-5.0 enabled. IBM explicitly warns that feature presence is not always obvious from server.xml alone because Liberty can load features through dependencies, so runtime logs such as the CWWKF0012I message are the better validation point.- Affected Liberty version range
- Affected
appSecurity-*feature enabled at runtime
- Non-affected feature sets are out of scope
- Mixed-version fleets may include many Liberty nodes that are not in the vulnerable band
- Feature enablement has to be verified per server, not guessed from a CMDB label
productInfo version --ifixes plus server logs can identify candidate systems. Remote scanners generally only see a version banner, if that.Win the race window
Turbo Intruder, custom async Python clients, or high-rate request harnesses would be the realistic weaponization path.- Ability to send repeated concurrent crafted requests
- Stable knowledge of the target request flow
- A timing window that is actually reachable in the target deployment
AC:His real here; many race bugs do not reproduce cleanly across production topologies- Load balancers, retries, sticky sessions, and thread scheduling can break exploit reliability
- WAFs and rate controls may not understand the bug, but they still make mass exploitation noisier
Read data past intended authorization boundaries
- Successful timing-window bypass
- Sensitive data behind the affected authorization path
- Impact appears limited to confidentiality
- Scope is bounded by what the compromised privileged account can reach in the application context
- No evidence this chains directly to system-level compromise
The supporting signals.
| In-the-wild status | No public evidence of active exploitation found in reviewed sources. Not listed in CISA KEV as of review. |
|---|---|
| Proof-of-concept availability | No public PoC or weaponized repo surfaced in reviewed sources. That absence does not prove safety, but it fits the race-condition + high-privilege friction profile. |
| EPSS | 0.00037 (very low). That is consistent with a niche, post-auth, high-complexity flaw rather than an internet-scale opportunistic bug. |
| KEV status | CISA KEV: No. No federal due date because there is no KEV entry. |
| CVSS vector meaning | CVSS:3.1/AV:N/AC:H/PR:H/UI:N/S:U/C:H/I:N/A:N means remote reachability in theory, but exploitation still needs high privileges and a high-complexity timing condition. Realistically, that is downward pressure on urgency. |
| Affected versions and features | IBM says Liberty 22.0.0.11 through 26.0.0.5 are affected only when appSecurity-3.0, appSecurity-4.0, or appSecurity-5.0 is enabled. |
| Fixed versions | Strategic fix is Liberty 26.0.0.6 or later. IBM also published interim fixes for APAR PH70798, including builds for 25.0.0.9, 25.0.0.12, 26.0.0.3, and 26.0.0.5. |
| Scanner and detection coverage | Tenable ships plugin 315541 for 22.0.0.11 < 26.0.0.6, but version-only checks can overstate risk if an interim fix is already installed. Local productInfo version --ifixes is the authoritative check for PH70798. |
| Exposure telemetry | I found no CVE-specific GreyNoise/KEV telemetry in public sources reviewed. Public internet fingerprinting for Liberty is also imperfect, so exposed-host counts should be treated as an inference problem, not a clean census. |
| Disclosure timeline / reporter | IBM's bulletin shows initial publication on 2026-05-19; the APAR download page shows modified 2026-05-27. I found no public researcher attribution or acknowledgement in IBM's bulletin. |
noisgate verdict.
The single biggest severity reducer is the prerequisite stack: authenticated remote access with high privileges before the race window even matters. This is a narrow, post-compromise authorization-bypass scenario with confidentiality-only impact, not a broadly reachable edge exploit.
Why this verdict
- Requires privileged access first:
PR:Hmeans the attacker already has a high-privileged authenticated foothold in the application path. That pushes this into post-initial-access territory and materially lowers enterprise patch urgency. - Race-condition reliability is poor at scale:
AC:His not decorative here; exploitation depends on hitting a timing window. Load balancers, session handling, concurrency behavior, and real production jitter all reduce repeatability. - Reachable population is narrower than the product label suggests: only Liberty
22.0.0.11through26.0.0.5withappSecurity-3.0/4.0/5.0enabled are affected. That is a smaller set than 'all WebSphere Liberty hosts.' - Blast radius is application-level confidentiality: the published vector shows
C:H/I:N/A:N. No integrity loss, no availability loss, and no evidence of direct code execution or host takeover. - Threat intel is cold: no KEV listing, no public PoC found, and EPSS is extremely low. That is strong downward pressure from the vendor's already-moderate baseline.
Why not higher?
To justify MEDIUM or above, I would want either broader exposure, lower attacker prerequisites, or active exploitation. Instead, this bug requires a high-privileged authenticated position and a finicky race condition on a feature-limited subset of Liberty servers. That is real risk, but it is not the kind of bug that should displace edge RCEs, auth bypasses, or KEV-listed issues in a 10,000-host program.
Why not lower?
I did not drop this to IGNORE because it is still a genuine authorization bypass with confidentiality impact on supported enterprise software, and IBM shipped a dedicated APAR/fix path for it. If you run the affected appSecurity-* features on sensitive applications, there is still enough value for an attacker to justify routine remediation.
What to do — in priority order.
- Validate feature exposure — Inventory which Liberty servers actually run
appSecurity-3.0,appSecurity-4.0, orappSecurity-5.0by checkingCWWKF0012Iinmessages.log/console.logand not justserver.xml. For aLOWverdict there is no mitigation SLA; do this as backlog hygiene so you do not waste cycles patching unaffected nodes blindly. - Shrink privileged reachability — Restrict access to privileged application workflows behind VPN, reverse proxy policy, IdP conditional access, and admin network segmentation. This cuts off the most decisive prerequisite — high-privileged remote access — and for
LOWseverity should be rolled into normal access-hardening work rather than an emergency change. - Review privileged session controls — Audit where Liberty-backed apps accept long-lived sessions, shared admin credentials, or broad role assignments. Tightening RBAC, PAM checkout, and session lifetime reduces the chance that a stolen privileged token can be used to reach the race condition; again, this is routine hardening, not break-fix.
- Use local fix validation before closure — Require
productInfo version --ifixesevidence forPH70798or a version at26.0.0.6+before marking systems remediated. This avoids false confidence from version-only scanners during the normal remediation cycle.
- A generic network IPS signature is not a dependable control here, because the exploit hinges on privileged application logic and a timing race rather than a simple malicious payload.
- Version-only external scanning does not tell you whether the affected
appSecurity-*feature is enabled, so it overstates population size and can mis-prioritize patch work. - EDR alone will not save you here; this is a request-level authorization problem, not malware spawning a suspicious process on the host.
Crowdsourced verification payload.
Run this on the target Liberty host from an auditor shell or your config-management agent. Invoke it as python3 liberty_cve_2026_5516_check.py /opt/ibm/wlp /opt/ibm/wlp/usr/servers/myserver on Linux/macOS or py liberty_cve_2026_5516_check.py C:\IBM\wlp C:\IBM\wlp\usr\servers\myserver on Windows; it needs permission to execute productInfo and read the target server's logs/config files.
#!/usr/bin/env python3
# CVE-2026-5516 Liberty check
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN, 3=USAGE/ERROR
import os
import re
import sys
import subprocess
import xml.etree.ElementTree as ET
from pathlib import Path
AFFECTED_FEATURES = {"appSecurity-3.0", "appSecurity-4.0", "appSecurity-5.0"}
FIX_APAR = "PH70798"
def parse_ver(v):
try:
return tuple(int(x) for x in v.strip().split('.'))
except Exception:
return None
def ver_in_range(v, low, high):
return low <= v <= high
def run_cmd(cmd):
try:
cp = subprocess.run(cmd, capture_output=True, text=True, timeout=20)
return cp.returncode, (cp.stdout or "") + (cp.stderr or "")
except Exception as e:
return 999, str(e)
def find_productinfo(liberty_root):
root = Path(liberty_root)
candidates = [
root / "bin" / "productInfo",
root / "bin" / "productInfo.bat",
root / "wlp" / "bin" / "productInfo",
root / "wlp" / "bin" / "productInfo.bat",
]
for c in candidates:
if c.exists():
return c
return None
def get_version_and_ifixes(productinfo):
rc1, out1 = run_cmd([str(productinfo), "version"])
rc2, out2 = run_cmd([str(productinfo), "version", "--ifixes"])
text = out1 + "\n" + out2
m = re.search(r"Product version:\s*([0-9]+(?:\.[0-9]+){1,3})", text)
version = m.group(1) if m else None
return version, text
def feature_hits_from_xml(server_xml):
hits = set()
try:
tree = ET.parse(server_xml)
root = tree.getroot()
for elem in root.iter():
tag = elem.tag.split('}')[-1]
if tag == "feature" and elem.text:
val = elem.text.strip()
if val in AFFECTED_FEATURES:
hits.add(val)
except Exception:
pass
return hits
def feature_hits_from_logs(server_dir):
hits = set()
log_candidates = [
Path(server_dir) / "logs" / "messages.log",
Path(server_dir) / "logs" / "console.log",
Path(server_dir) / "logs" / "trace.log",
]
for lp in log_candidates:
if not lp.exists():
continue
try:
with lp.open("r", encoding="utf-8", errors="ignore") as fh:
for line in fh:
if "CWWKF0012I" in line or any(f in line for f in AFFECTED_FEATURES):
for feat in AFFECTED_FEATURES:
if feat in line:
hits.add(feat)
except Exception:
pass
return hits
def main():
if len(sys.argv) < 2:
print("UNKNOWN - usage: liberty_cve_2026_5516_check.py <liberty_root> [server_dir]")
sys.exit(3)
liberty_root = sys.argv[1]
server_dir = sys.argv[2] if len(sys.argv) > 2 else None
productinfo = find_productinfo(liberty_root)
if not productinfo:
print("UNKNOWN - could not locate Liberty productInfo command")
sys.exit(2)
version_str, ifix_text = get_version_and_ifixes(productinfo)
if not version_str:
print("UNKNOWN - could not determine Liberty version from productInfo")
sys.exit(2)
version = parse_ver(version_str)
if not version:
print(f"UNKNOWN - unparseable Liberty version: {version_str}")
sys.exit(2)
if FIX_APAR in ifix_text or version >= parse_ver("26.0.0.6"):
print(f"PATCHED - Liberty {version_str} with {FIX_APAR} present or version >= 26.0.0.6")
sys.exit(0)
low = parse_ver("22.0.0.11")
high = parse_ver("26.0.0.5")
if not ver_in_range(version, low, high):
if version > high:
print(f"PATCHED - Liberty {version_str} is newer than affected range")
sys.exit(0)
print(f"UNKNOWN - Liberty {version_str} is outside IBM's published affected range; verify support status manually")
sys.exit(2)
# Affected version band: need runtime feature confirmation.
features = set()
if server_dir:
server_xml = Path(server_dir) / "server.xml"
if server_xml.exists():
features |= feature_hits_from_xml(server_xml)
features |= feature_hits_from_logs(server_dir)
if features:
feats = ", ".join(sorted(features))
print(f"VULNERABLE - Liberty {version_str} in affected range and runtime/config indicates: {feats}")
sys.exit(1)
print(f"UNKNOWN - Liberty {version_str} is in affected range, but affected appSecurity feature use was not confirmed. Check CWWKF0012I in server logs and confirm whether {FIX_APAR} interim fix is installed.")
sys.exit(2)
if __name__ == "__main__":
main()
If you remember one thing.
22.0.0.11-26.0.0.5 and verify whether appSecurity-3.0/4.0/5.0 is actually running; then use productInfo version --ifixes to find systems already covered by PH70798. For a LOW noisgate verdict there is no noisgate mitigation SLA and no noisgate remediation SLA beyond backlog hygiene, so fold affected systems into your next routine Liberty maintenance cycle, prioritize externally reachable or highly sensitive apps first, and close them only after confirming PH70798 or 26.0.0.6+ on-host.Sources
- IBM Security Bulletin 7273425
- IBM APAR PH70798 interim fix page
- IBM: How to determine if Liberty is using a specific feature
- IBM Docs: productInfo command
- IBM Fix list for WebSphere Application Server Liberty
- CISA Known Exploited Vulnerabilities Catalog
- FIRST EPSS data and stats
- Tenable plugin coverage for CVE-2026-5516
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.