This is a badge printer at your front desk that sometimes spits out yesterday’s master keys with today’s visitor pass
CVE-2026-3055 is a memory overread in NetScaler ADC and NetScaler Gateway that is reachable over the network only when the appliance is configured as a SAML Identity Provider (IdP). Affected supported builds are 14.1 before 14.1-60.58, 13.1 before 13.1-62.23, and 13.1-FIPS / 13.1-NDcPP before 13.1-37.262; vendor guidance also points customers to 14.1-66.59+ on the later 14.1 train. watchTowr showed the CVE actually covers at least two leak paths: /saml/login and /wsfed/passive?wctx, both returning leaked process memory via the NSC_TASS cookie.
The vendor’s CRITICAL label is directionally right once the SAML IdP prerequisite is met, because this sits on the identity edge and the leaked memory can expose session material, request data, and potentially credentials or tokens that turn an info leak into real account takeover. The one real downward pressure is exposure population: not every NetScaler is a SAML IdP, so the vendor’s blanket 9.8 slightly overstates fleet-wide prevalence. That said, KEV listing, active exploitation, unauthenticated reachability, and identity-system blast radius keep this squarely in emergency territory.
4 steps from start to impact.
Internet recon finds candidate NetScalers
- Target NetScaler is reachable from the attacker over HTTPS
- Appliance is customer-managed rather than Citrix-managed cloud service
- Service exposes endpoints consistent with NetScaler Gateway / ADC
- Not every NetScaler is configured as a SAML IdP
- Private-only gateways or IP-restricted edges fall out of reach
- Some orgs terminate traffic upstream or geofence access
SAML IdP path is probed with crafted requests
/saml/login or /wsfed/passive?wctx using logic published by watchTowr and operationalized in public scanner content. On vulnerable systems, malformed or minimal parameters cause the appliance to read stale process memory and return it in the NSC_TASS cookie.- Appliance is configured as a SAML IdP
- Affected vulnerable build is still running
- Relevant endpoint is exposed and not blocked upstream
- If the box is patched, the safe check stops working and returns the patched behavior
- If SAML IdP is not configured, the attack path usually collapses to non-vulnerable behavior
- Some leaks are noisier or less deterministic on low-traffic systems
/saml/login or /wsfed/passive, but the traffic is small and can resemble protocol fuzzing. watchTowr noted unusual messages may land in /var/log/ns.log when logging is verbose.Memory disclosure yields reusable secrets
/wsfed/passive?wctx path can return kilobytes of memory and do so more reliably than the smaller /saml/login leak path.- The crafted request reaches the vulnerable code path
- Leaked memory contains live or recently used security-relevant data
- Attacker can iterate requests without being blocked
- Memory leaks are opportunistic: the exact payload depends on what was recently in process memory
- Not every response yields high-value material
- Session lifetime and downstream token binding can reduce reuse
Leaked tokens become real access
- Leaked data includes valid session or credential artifacts
- Those artifacts are still valid and accepted by downstream services
- The attacker can replay or redeem them before expiry or revocation
- Short-lived sessions, session revocation, or downstream re-authentication can limit utility
- Strong segmentation of admin planes can contain follow-on movement
- Some tokens may be audience-bound or expire quickly
The supporting signals.
| In-the-wild status | Yes. CISA added CVE-2026-3055 to KEV on 2026-03-30. watchTowr says honeypots saw exploitation from known threat-actor source IPs as of 2026-03-27. |
|---|---|
| Proof-of-concept / tooling | Technical exploitation details are public from watchTowr Part 1 and Part 2. Rapid7 states a Metasploit module is available, and ProjectDiscovery shipped a Nuclei template tagged critical and kev. |
| EPSS | 0.89855 from the user intel block — extremely high. *Percentile was not provided in the prompt; treat this as top-tier exploitation likelihood regardless.* |
| KEV dates | Listed: 2026-03-30. CISA due date for FCEB: 2026-04-02, per the NVD change log reflecting the KEV update. |
| CVSS reality check | Vendor / NVD CVSS v3.1 is CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H. That vector is technically severe, but the real-world catch is the SAML IdP configuration prerequisite, which narrows exposed population even while leaving each exposed host highly dangerous. |
| Affected versions | Supported affected builds: 14.1 < 14.1-60.58, 13.1 < 13.1-62.23, 13.1-FIPS / 13.1-NDcPP < 13.1-37.262. Censys also notes 12.1 and 13.0 are EOL and do not receive fixes. |
| Fixed versions | Vendor-fixed releases include 14.1-60.58, 14.1-66.59+, 13.1-62.23+, and 13.1-FIPS / NDcPP 13.1-37.262+. There is no fix path for EOL trains other than upgrade / replacement. |
| Exposure / scanning data | Censys published an exposure advisory and map for this CVE, confirming broad internet visibility of candidate NetScaler assets. Rapid7 shipped authenticated detection content, and community scanner coverage is already widespread via Nuclei and Metasploit. |
| Disclosure / provenance | Disclosed 2026-03-23 by NetScaler / Cloud Software Group. The vendor says the issue was identified internally through ongoing security reviews. |
| Researcher / org notes | watchTowr Labs researchers Aliz Hammond and McCaulay Hudson published the most useful public technical analysis. Their Part 2 finding matters operationally because it says one CVE covers at least two memory-overread bugs on separate endpoints. |
noisgate verdict.
The decisive amplifier is active exploitation of an unauthenticated bug on the identity edge. The decisive friction is that only SAML IdP-configured NetScalers are affected; that narrows population, but for any exposed match the combination of KEV status and token-leak potential is enough to keep this in the top bucket.
Why this verdict
- KEV + exploitation evidence: CISA KEV and watchTowr honeypot evidence remove the usual debate about whether attackers will operationalize this.
- Unauthenticated internet-edge reachability: no creds, no user click, no agent foothold. That is always bad, and worse when the target is a gateway or IdP role.
- Identity-edge blast radius: even though this is 'just' a memory overread, the appliance handles authentication state. Leaking cookies, session material, or request data can translate into session hijack and downstream access.
- Configuration prerequisite trims prevalence, not urgency: requiring SAML IdP mode absolutely narrows the fleet. But it does not meaningfully soften severity for the subset that is exposed, because those are usually high-value federation chokepoints.
- Public tooling lowers attacker cost: watchTowr published detailed detection and exploit behavior; Rapid7 notes a Metasploit module; Nuclei content exists. That shortens time from advisory to mass scanning.
Why not higher?
It is not a universal pre-auth bug across all NetScaler deployments; the SAML IdP requirement is real downward pressure. And this is not direct RCE from the public reporting we have — the attacker still has to turn leaked memory into usable access material.
Why not lower?
Calling this merely HIGH would underweight the two things that matter most: confirmed exploitation and identity-edge exposure. An unauthenticated bug on a public-facing auth appliance that can leak sessions or credentials is exactly how enterprises end up with quiet, fast follow-on access.
What to do — in priority order.
- Restrict SAML IdP exposure now — If business allows it, disable SAML IdP mode or remove external reachability for affected NetScalers immediately. Because this is KEV-listed / actively exploited, deploy this compensating control within hours while patching is in flight.
- Put an upstream allowlist in front — Apply IP allowlisting, geofencing, or VPN-only access at the load balancer, CDN, reverse proxy, or firewall in front of the appliance so random internet traffic cannot hit
/saml/loginor/wsfed/passive. For a CRITICAL KEV issue, do this within hours if you cannot patch first. - Expire sessions and rotate trust material — Because the failure mode is memory disclosure of session/auth artifacts, terminate active sessions and rotate any exposed federation or appliance secrets after containment and patching. Start this within hours for exposed internet-facing SAML IdP appliances.
- Increase edge logging and hunt for endpoint probes — Raise logging on NetScaler and upstream devices and specifically hunt for abnormal hits to
/saml/loginand/wsfed/passive, especially malformed or repetitive requests. Do this within hours because post-patch review is your best chance to spot pre-patch token theft.
- MFA alone does not save you if the attacker steals a valid session or token and replays it downstream.
- EDR on user workstations misses the core exploit path because the compromise happens on the appliance before any endpoint is involved.
- Generic WAF signatures are not enough to bet the estate on; the requests are small, path-specific, and may look like odd but valid auth traffic.
- Waiting for scanner coverage is the wrong move here; public probe logic is already available and attackers are not waiting for your next authenticated scan window.
Crowdsourced verification payload.
Run this from an auditor workstation that can reach the NetScaler over HTTPS; no credentials are required. Invoke it as python3 check_cve_2026_3055.py https://netscaler.example.com (optionally --insecure); it performs a safe network check against /saml/login and returns VULNERABLE, PATCHED, or UNKNOWN.
#!/usr/bin/env python3
# check_cve_2026_3055.py
# Safe network verification for CVE-2026-3055 on NetScaler ADC / Gateway.
# Exit codes:
# 0 = PATCHED
# 1 = VULNERABLE
# 2 = UNKNOWN / error
import sys
import ssl
import argparse
import urllib.request
import urllib.parse
import urllib.error
SAFE_SAMLREQUEST = (
"PHNhbWxwOkF1dGhuUmVxdWVzdCB4bWxuczpzYW1scD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnByb3RvY29sIiANCn"
"htbG5zOnNhbWw9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iICANCklEPSJfMSINClZlcnNpb249IjIu"
"MCIgUHJvdmlkZXJOYW1lPSJteSBwcm92aWRlciIgDQpEZXN0aW5hdGlvbj0iaHR0cDovL3dhdGNodG93ci9zYW1sLnBocCIgDQ"
"pQcm90b2NvbEJpbmRpbmc9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpiaW5kaW5nczpIVFRQLVBPU1QiIA0KPg0KICA8c2"
"FtbDpJc3N1ZXI+aHR0cDovL3dhdGNodG93ci9zYW1sLnBocDwvc2FtbDpJc3N1ZXI+DQo8L3NhbWxwOkF1dGhuUmVxdWVzdD4="
)
PATCHED_MARKERS = [
"Parsing of presented Assertion failed",
"Please contact your administrator",
]
UNKNOWN_MARKERS = [
"404", "not found", "forbidden", "access denied"
]
def build_opener(insecure=False):
if insecure:
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
https_handler = urllib.request.HTTPSHandler(context=ctx)
return urllib.request.build_opener(https_handler)
return urllib.request.build_opener()
def normalize_base(url: str) -> str:
url = url.strip()
if not url.startswith(("http://", "https://")):
url = "https://" + url
return url.rstrip("/")
def main():
parser = argparse.ArgumentParser(description="Safe check for CVE-2026-3055 on NetScaler")
parser.add_argument("target", help="Base URL, e.g. https://netscaler.example.com")
parser.add_argument("--insecure", action="store_true", help="Ignore TLS certificate validation")
args = parser.parse_args()
base = normalize_base(args.target)
url = base + "/saml/login"
data = urllib.parse.urlencode({"SAMLRequest": SAFE_SAMLREQUEST}).encode()
headers = {
"User-Agent": "noisgate-cve-2026-3055-check/1.0",
"Content-Type": "application/x-www-form-urlencoded",
}
req = urllib.request.Request(url, data=data, headers=headers, method="POST")
opener = build_opener(args.insecure)
try:
with opener.open(req, timeout=15) as resp:
body = resp.read(8192).decode("utf-8", errors="ignore")
set_cookie_headers = resp.headers.get_all("Set-Cookie") or []
cookie_blob = "\n".join(set_cookie_headers)
if "NSC_TASS=" in cookie_blob:
print("VULNERABLE")
sys.exit(1)
if any(marker in body for marker in PATCHED_MARKERS):
print("PATCHED")
sys.exit(0)
if any(marker.lower() in body.lower() for marker in UNKNOWN_MARKERS):
print("UNKNOWN")
sys.exit(2)
print("UNKNOWN")
sys.exit(2)
except urllib.error.HTTPError as e:
try:
body = e.read(8192).decode("utf-8", errors="ignore")
except Exception:
body = ""
headers = e.headers if hasattr(e, "headers") else {}
set_cookie_headers = headers.get_all("Set-Cookie") if headers else []
cookie_blob = "\n".join(set_cookie_headers or [])
if "NSC_TASS=" in cookie_blob:
print("VULNERABLE")
sys.exit(1)
if any(marker in body for marker in PATCHED_MARKERS):
print("PATCHED")
sys.exit(0)
print("UNKNOWN")
sys.exit(2)
except Exception:
print("UNKNOWN")
sys.exit(2)
if __name__ == "__main__":
main()
If you remember one thing.
Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.