## https://sploitus.com/exploit?id=PACKETSTORM:225078
=======================================================================
SUMMARY
=======================================================================
Zscaler Client Connector (ZCC) for macOS ships, in its default
configuration, in a fail-open state. A standard (non-admin) local user
can suspend the agent's user-space enforcement processes during the
client's "Restart Services" / "Repair App" workflow by sending POSIX
SIGSTOP signals to processes the user already owns. The anti-tampering
watchdog does not detect this: a stopped ('T' state) process still
exists in the process table, and the watchdog's liveness check does
not distinguish "present" from "running." While suspended:
- ZIA/ZPA policy enforcement (URL filtering, SSL inspection, cloud
firewall, malware scanning) is not applied
- DLP content inspection is not applied
- Endpoint logging/telemetry to Zscaler is halted
- Network traffic reverts to the system default gateway, completely
bypassing the Zscaler tunnel
- The management console continues to report the device as
"Connected" -- a false operational status throughout
The condition is not a momentary blip during reconnect. Suspended
processes are not auto-recovered by the watchdog; the bypass persists
until the processes are resumed (SIGCONT) or the machine is rebooted.
The protective ("fail-close") behavior is an opt-in administrative
configuration that must be explicitly deployed via MDM/JAMF. The
vulnerable state is the factory default.
Vulnerability class: CWE-1188 (Insecure Default Initialization)
CWE-636 (Not Failing Securely / Failing Open)
CWE-367 (Time-of-check Time-of-use Race Cond.)
CVSS 3.1: 7.1 HIGH
AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N
MITRE ATT&CK: T1562.001 (Impair Defenses: Disable or
Modify Tools)
CERT/CC: VU#372528 (filed 2026-02-11 as
VRF#26-02-HTQRQ)
CVE Program: CNA-LR request CAN-2026-2032427 pending with
MITRE (filed 2026-06-24) after CNA Zscaler
declined assignment
Privileges required: Standard user (no sudo, no admin group)
=======================================================================
AFFECTED PRODUCT
=======================================================================
Vendor: Zscaler, Inc.
Product: Zscaler Client Connector (ZCC) for macOS
Versions: 4.3.0.240 (originally reported)
4.5.2 LTS -- reproduced and CONFIRMED IN WRITING BY
ZSCALER'S OWN RESEARCH TEAM (see VENDOR
ADMISSIONS below)
4.7.0.155 (n-1 supported) -- independently reproduced by
the researcher in factory-default configuration
Fixed in: 4.5.2.4, ONLY when the "Firewall Enhancement for Security"
fail-close JAMF configuration is explicitly, separately
enabled. This is not the default state of 4.5.2.4 or any
later version. Per Zscaler (confirmed on the 2026-04-21
call), enabling this fail-close configuration also removes
the end user's ability to restart the Zscaler client --
a standard troubleshooting action -- so the "fix" is a
functionality trade-off rather than a transparent patch.
See REMEDIATION for why this matters.
Platform: macOS (Sequoia / Tahoe). Not tested on Windows ZCC. Note
that a related but architecturally distinct Windows Service
Restart bypass was independently assigned CVE-2023-28802 by
Zscaler (see CVE PRECEDENT below).
=======================================================================
ROOT CAUSE
=======================================================================
The defect is an insecure default combined with a TOCTOU race in the
restart sequence:
1. INSECURE DEFAULT (CWE-1188)
Out of the box, ZCC for macOS does not fail closed when its
user-space enforcement components stop processing. The protective
fail-close behavior is an opt-in administrative configuration that
must be explicitly deployed. Absent that explicit configuration --
i.e. in the factory-default state -- the product fails open.
2. TOCTOU RACE + WATCHDOG GAP (CWE-367 / CWE-636)
During "Restart Services" / "Repair App", there is a window in
which an enforcement process can be suspended (SIGSTOP) before the
anti-tampering watchdog re-attaches and validates process health.
The watchdog's liveness check is satisfied by the process's
continued existence in the process table; a stopped (state 'T')
process still satisfies that check. The watchdog does not detect
that enforcement has ceased, and does not restore it.
Because the secure state requires an explicit administrative opt-in,
and the DEFAULT state is exploitable by an unprivileged user, this is
CWE-1188 -- not a user-introduced misconfiguration, and not (per
Zscaler's final stated position) merely "a configuration choice."
Note on the moving assessment: over the course of coordination
Zscaler's stated basis for declining changed as each was addressed --
first that the issue only affected 4.3 (end-of-life / outside the n-2
support window); then, after its own Research team confirmed
reproduction on the supported 4.5.2 LTS in writing, that the 4.5.2
confirmation was a "miscommunication"; then a request to re-demonstrate
on 4.7; and finally that the behavior is not a vulnerability at all.
The dated record of these positions is in the VENDOR COORDINATION
TIMELINE below.
=======================================================================
REPRODUCTION (standard user, no sudo required)
=======================================================================
1. Confirm enforcement is active:
curl ifconfig.me
# returns a Zscaler egress IP -- traffic is tunneled/enforced
2. Trigger the client's "Restart Services" / "Repair App" function
while a PoC script polls for the target ZCC process(es) and issues
SIGSTOP within the restart race window.
3. Confirm process state:
ps aux | grep -i zscaler
# target process(es) now in 'T' (stopped) state, still present
# in the process table
4. Confirm the bypass is active:
curl ifconfig.me
# now returns the host's REAL ISP IP -- traffic egresses via the
# system default gateway with NO Zscaler enforcement
5. The condition persists. Suspended processes are not auto-recovered;
enforcement does not resume on its own until the processes are
resumed (SIGCONT) or the machine is rebooted.
Reproduced independently by the researcher on ZCC 4.7.0.155 (n-1
supported version) in an unmodified, factory-default configuration.
See CONFIGURATION AUDIT below for the forensic verification that no
fail-close policy was deployed on the test endpoint.
PoC script and full technical writeup:
https://gist.github.com/usualdork/84d156ab09027755f4c405b2f87af230
PoC video (before/after external-IP change, sustained bypass window,
no auto-recovery):
https://drive.google.com/file/d/14KNjqfMUf66IFyXFu9KfeUyFyiZ6sMaH/view
The original Bugcrowd closure rationale -- that SIGSTOP "only
terminates zstray" and that stopping the tunnel "requires sudo" -- is
directly contradicted by this video: if the tunnel continued
enforcing, the external IP would remain the Zscaler egress IP
throughout. It does not.
=======================================================================
CONFIGURATION AUDIT -- FAIL-OPEN IS THE FACTORY DEFAULT
=======================================================================
To close off the vendor's suggestion that the bypass only reproduces
where an administrator has failed to enable fail-close, the researcher
performed a forensic audit of the managed test endpoint:
ZscalerTunnelStatus.plist -- empty
com.zscaler.ZscalerTunnel MDM managed pref -- empty
ZscalerTunneldb fail strings -- empty
sudo profiles show -all -- no tunnel policy,
no app profile,
no fail-close
configuration of
any kind
The endpoint's MDM had pushed exactly one Zscaler-related profile: an
SSL inspection certificate. No tunnel policy or fail-close
configuration was ever deployed. The device was running the factory-
default ZCC enforcement state, which is fail-open.
This is what maps the finding to CWE-1188: the DEFAULT shipped state
is the exploitable one. An explicit administrative action is required
to reach the protected state -- not to reach the vulnerable state.
=======================================================================
VENDOR ADMISSIONS (IN WRITING, FROM ZSCALER'S OWN TEAMS)
=======================================================================
This is not solely the researcher's characterization. Zscaler's own
Support and Research teams confirmed the finding in writing, via
Zscaler Support Case #06171397:
2026-04-14 -- Zscaler Support, in writing: Zscaler's Research team
reproduced the issue on macOS ZCC 4.5.2 LTS -- a currently supported
Long-Term-Support release -- and stated it was fixed only in
4.5.2.4 with the "Firewall Enhancement for Security" configuration
deployed.
2026-05-03 -- Zscaler PSIRT (Sidharth Krishnan), in writing: "if
App Restart is disabled, all versions of ZCC on Mac are protected"
-- an admission that, absent that non-default administrative
action, ALL versions remain exploitable in their default state.
2026-05-08 -- Zscaler RSH (Research) team document, "macOS Local
Bypass via SIGSTOP of Zscaler Client Connector Processes," provided
via the same support case. Verbatim:
"A local macOS user can bypass Zscaler security enforcement by
running a shell script that sends a recursive SIGSTOP to
Zscaler-related processes. When the processes are paused, core
protections such as ZIA/ZPA enforcement and endpoint
logging/telemetry are halted, leaving the device in an
effectively unprotected state."
and:
"These remediation options are supported across all active
supported Zscaler Client Connector versions for macOS,
specifically 4.5.2 LTS and subsequent releases."
Taken together: Zscaler's own documentation establishes that the
behavior is real, is impactful ("effectively unprotected state"), and
is present on currently supported versions -- in Zscaler's own words,
"4.5.2 LTS and subsequent releases."
=======================================================================
IMPACT
=======================================================================
Control Normal After Bypass
-----------------------------------------------------------------
URL filtering / SSL inspect ENFORCED NOT ENFORCED
DLP content inspection ENFORCED NOT ENFORCED
Cloud firewall / malware scan ENFORCED NOT ENFORCED
Endpoint telemetry to Zscaler ACTIVE HALTED
Network egress Zscaler tunnel System default gw
Management console status Connected Connected (FALSE)
Any standard user on a managed macOS endpoint can exfiltrate data,
reach policy-blocked destinations, or fetch payloads with zero
inspection and zero telemetry, while the SOC's management console
continues to report the device as healthy and enforcing throughout.
=======================================================================
CVE PRECEDENT
=======================================================================
CVE-2021-26737 was assigned by Zscaler (a CVE Numbering Authority)
for ZCC macOS prior to 3.6:
"The Zscaler Client Connector for macOS prior to 3.6 did not
sufficiently validate RPC clients. A local adversary without
sufficient privileges may be able to shutdown the Zscaler tunnel by
exploiting a race condition."
This is the same product, same platform, same local-unprivileged
attacker model, and same race-condition primitive as the present
finding.
CVE-2023-28802 was assigned by Zscaler for a Service Restart bypass
on the same product line (Windows), fixed in 4.2.0.149.
The present finding produces an equal or greater impact via the
identical attack surface (the Restart/Repair workflow) on a currently
supported macOS version. Zscaler's 2026 rationale for declining
CVE assignment -- that the behavior is local user action, is
documented, and has configurable mitigations -- would equally have
excluded CVE-2021-26737, which Zscaler nonetheless assigned. Zscaler
has not, in any coordination correspondence, addressed this
inconsistency with its own CVE record.
=======================================================================
VENDOR COORDINATION TIMELINE
=======================================================================
2026-02-11 Reported to CERT/CC via VINCE (VRF#26-02-HTQRQ);
case opened as VU#372528
2026-02-12 Submitted to Zscaler via Bugcrowd
2026-03-12 Bugcrowd closed: "SIGSTOP only terminates zstray;
stopping ZSTunnel requires sudo." Rebutted by PoC video
showing real-ISP-IP routing during the bypass window
2026-03-27 Zscaler Support call. Written summary acknowledges ZCC
"stays in the frozen state persistently, unless the
machine is rebooted," fail-open confirmed, flagged as a
possible TOCTOU match. Reproduced on 4.3.0.240
2026-04-14 Zscaler Support confirms IN WRITING: Research team
reproduced on 4.5.2 LTS (supported); fixed only in
4.5.2.4 with opt-in Firewall Enhancement config
2026-04-21 Meeting with Zscaler PSIRT/leadership. Zscaler
characterizes the issue as a "known issue" in 4.3;
declines CVE citing the n-2 support window; the April 14
written confirmation on 4.5.2 LTS is characterized on the
call as a "miscommunication." Researcher subsequently
reproduces on ZCC 4.7.0.155 (n-1, factory default) and
forensically confirms no fail-close config is deployed
2026-05-03 Zscaler PSIRT confirms in writing that all versions are
protected ONLY if App Restart is disabled (non-default
admin action)
2026-05-07 Zscaler Support closes the ticket: "the Engineering team
has discussed the CVE decision and will not be
proceeding" -- no named PSIRT member, no written
technical rationale
2026-05-08 Zscaler RSH team provides written document admitting the
bypass affects "all active supported ZCC versions for
macOS ... 4.5.2 LTS and subsequent releases," leaving the
device in an "effectively unprotected state"
2026-05-08 Zscaler Director (Dhaval Parekh) proposes a follow-up
meeting on the coordination platform to discuss "why this
is not considered a vulnerability" -- a reversal from the
April 21 "known issue" position
2026-05-12 Zscaler issues a formal written CVE declination
(local user action / documented policy / configurable
mitigations)
2026-05-12 CVE Program dispute filed with MITRE
2026-05-20 }
2026-05-26 } CISA coordinator asks Zscaler THREE TIMES, in writing,
2026-06-02 } on the coordination platform to state and justify its
} CVE position. No vendor response for weeks
2026-06-17 Zscaler claims its team could not reproduce persistence
beyond a brief tunnel-restart interval on version 4.7,
and requests a live debugging session -- after already
confirming the finding in writing on 4.5.2 LTS
2026-06-23 Zscaler's final written position: the fail-open behavior
is real but is "the expected outcome of an administrative
configuration," not a vulnerability. CISA declines CVE
assignment citing CNA Rule 4.1.3 and closes VU#372528
2026-06-24 CNA-LR CVE-ID assignment request filed with MITRE under
CVE Program Rule 4.2.1.2 (CAN-2026-2032427), on the basis
that the CNA has acknowledged the behavior in writing but
declined to assign
2026-07-03 Public disclosure. Partial fix exists (4.5.2.4) but is
NOT the default configuration of any shipping version, and
enabling it removes end-user client-restart capability.
No CVE assigned. CNA-LR request pending with MITRE.
=======================================================================
REMEDIATION
=======================================================================
1. IMMEDIATE (administrators)
- Disable end-user "Restart Services" / "Repair App" via the
Zscaler Client Connector Portal (Administration > Client
Connector Support > App Supportability), OR
- Deploy the "Firewall Enhancement for Security" fail-close
configuration via MDM/JAMF for all managed macOS endpoints.
Note that neither of these is the default state of any shipping
ZCC version as of this advisory. Administrators should also be
aware of a functionality trade-off: per Zscaler, enabling the
fail-close configuration removes the end user's ability to restart
the Zscaler client. Because client restart is a routine
connectivity-troubleshooting step, organizations are effectively
pushed toward leaving the insecure default in place to preserve
usability -- which is itself the core of why this is an insecure-
default (CWE-1188) condition rather than a neutral configuration
choice.
2. VENDOR-SIDE (architectural)
- Fail closed by default when enforcement components are not
processing, rather than requiring opt-in configuration.
- Watchdog liveness checks should treat a stopped (state 'T')
process as non-enforcing and restore or fail closed, rather than
treating process-table presence as sufficient evidence of health.
- Implement signal interception via Apple's Endpoint Security
Framework: ES_EVENT_TYPE_AUTH_SIGNAL (intercepts POSIX signals
including SIGSTOP, available since macOS 10.15) and
ES_EVENT_TYPE_AUTH_PROC_SUSPEND_RESUME (task-level suspend/
resume interception, available since macOS 11.0). Either can
deny suspension of enforcement processes before it takes effect.
This is the class of mechanism other endpoint security agents
use for SIGSTOP self-protection.
- The management console should not report a device as Connected/
healthy while enforcement is suspended.
=======================================================================
RESEARCHER
=======================================================================
Name: Manish Tripathy
Contact: manishyash.tripathy@gmail.com
CERT/CC: VU#372528 (VRF#26-02-HTQRQ, filed 2026-02-11)
Zscaler reference: Support Case #06171397
CVE Program: CAN-2026-2032427 (CNA-LR request pending)
Full writeup: https://gist.github.com/usualdork/84d156ab09027755f4c405b2f87af230
Disclosure policy: Coordinated disclosure via CERT/CC. Original
expected public date 2026-05-26 was set and passed
during continued coordination; this advisory
follows Zscaler's final written declination and
CISA's closure of VU#372528.