CVE-2026-55978 — SecureAge CatchPulse Security Advisory

CVE-2026-55978

Improper Access Control in IOCTL Handler Leading to Security Policy Bypass / SAAppWhitelistingPort

Severity

8.4 High

CVSS v3.1

8.4 High
Vector:
AV:L/AC:L/PR:L/UI:N/S:C/C:N/I:H/A:H

Access required

Standard local user

Vendor: SecureAge Technology   |   Product: CatchPulse   |   Affected versions: v10.10.0 and earlier

Reported by: Ang Kar Min   |   Report date: 2026-06-23; updated 2026-06-25   |   Public disclosure: 2026-08-06

Core finding

A non-administrative local user can disable CatchPulse application whitelisting by connecting to an unrestricted kernel filter communication port and sending an unprivileged ExpiryDate update command. The result is a trust-all/non-blocking state in which previously blocked executables run without prompts or enforcement.

Contents

  1. Executive summary
  2. Vulnerability overview
  3. CVSS score and derivation
  4. Evidence and screenshots
  5. Root cause analysis
  6. Impact assessment
  7. Proof-of-concept validation summary
  8. Remediation recommendations
  9. Timeline

1. Executive summary

CatchPulse v10.9.3 and v10.10.0 allow a standard local user to disable the product's application whitelisting enforcement layer without administrator rights or user interaction.

The issue is caused by two independent weaknesses that combine into a complete bypass. First, the kernel minifilter exposes \SAAppWhitelistingPort with a NULL discretionary access control list (DACL), allowing any local process to connect. Second, the command dispatcher accepts cmd=6 for ExpiryDate updates without checking that the caller is privileged. A caller can therefore send a past ExpiryDate and cause the service/driver path to enter a non-blocking, trust-all mode.

Why this is important

Application whitelisting is intended to be a system-wide control that prevents unknown or untrusted code from running. This vulnerability removes that control rather than bypassing a single policy decision. It was confirmed using a standard user account and can be triggered through Microsoft-signed tooling, making it relevant even in locked-down environments where PowerShell or custom executables are restricted.

  • Confirmed with CatchPulse v10.9.3 on Windows Server 2025 using a licensed install; other editions and versions have not yet been confirmed.
  • Confirmed end-to-end: previously blocked unsigned test binaries executed after the ExpiryDate write.
  • The bypass survives service-level recovery attempts; a reboot/reload of the kernel component is required to restore enforcement.
  • With a forged past ExpiryDate left in the registry, offline systems can repeatedly re-enter the bypass state after reboot.
  • A structurally similar missing privilege check exists in cmd=12, which should be fixed at the same time.

2. Vulnerability overview

ItemDetails
Affected binarysaappctl.sys - installed SHA-256 40267B24877519DDF41E4CB2566521CD497336FBE8BA64E55E5E9AEDF802EDD8
Component typeFSFilter ContentScreener kernel minifilter, altitude 262510
Affected interface\SAAppWhitelistingPort
Affected versionsCatchPulse v10.9.3 and v10.10.0.
Test environmentWindows Server 2025 with a licensed CatchPulse install.
Suggested weakness classificationCWE-862 - Missing Authorization; related access-control issue: CWE-284 - Improper Access Control.
Primary vulnerable commandcmd=6 - ExpiryDate write
Related vulnerable commandcmd=12 - HKLM\...\SAAppCtl\Db\InitialWhitelistSpeed write
Attacker requirementsLocal standard user. No administrator privileges and no UI interaction required.
Observed resultApplication whitelisting enters non-blocking/trust-all mode; previously blocked executables run without prompt.
Persistence characteristicSurvives failed service restart and can re-activate after reboot if forged registry value remains, especially on offline systems.

Confirmed exploit chain: connect to unrestricted port -> send cmd=6 with past ExpiryDate -> registry write succeeds -> service logs license-expired state -> enforcement enters trust-all/non-blocking mode -> blocked executable runs.

2.1 CVSS v3.1 score and derivation

The vulnerability is scored as CVSS v3.1 (8.4 High). It disables the product's core security enforcement layer rather than merely bypassing one individual policy decision.

MetricValueRationale
Attack VectorAV:L - LocalThe attacker needs local execution on the affected Windows machine. This is not independently network-exploitable.
Attack ComplexityAC:L - LowThe path does not require a race condition, special timing, memory corruption, or unusual system state. A standard user can connect to the exposed filter port and send one accepted message.
Privileges RequiredPR:L - LowThe attacker does not need administrator rights. A normal local user account is sufficient.
User InteractionUI:N - NoneNo administrator or victim user needs to click, approve, or interact with anything after the attacker runs the request.
ScopeS:C - ChangedThe vulnerable component is CatchPulse's privileged enforcement path, but the effect extends to the wider protected system by removing application-whitelisting enforcement.
ConfidentialityC:N - NoneThe finding does not directly demonstrate disclosure of files, credentials, or private data.
IntegrityI:H - HighThe attacker can run executables that CatchPulse previously blocked, defeating the system's application-control policy.
AvailabilityA:H - HighThe application-whitelisting protection layer can be placed into a non-blocking/trust-all state and remain disabled until reboot or longer if the forged expiry state persists.

Full vector: CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:N/I:H/A:H

3. Evidence and screenshots

The screenshots below show the vulnerability moving from baseline enforcement, to successful unprivileged command execution, to observed bypass. Figure captions identify what each screenshot proves and why it matters.

CatchPulse baseline prompt showing unsigned test executable flagged as untrusted
Figure 1 - Baseline enforcement: CatchPulse flags the unsigned test executable as an untrusted file and prompts to continue blocking.
Command Prompt showing blocked execution before the bypass
Figure 2 - Baseline command-line result: before the exploit, the same test executable is blocked with "The system cannot execute the specified program."
Cropped PowerShell output showing IsAdmin false and success statuses
Figure 3 - Readability crop of the PoC output: IsAdmin=False, FilterSendMessage HRESULT=0x00000000, kernel outBuf status 0x00000000, and registry confirmation.
Command Prompt showing bypass confirmed message after exploit
Figure 4 - Bypass confirmed: the same executable that was blocked in Figure 2 now runs and prints "BYPASS CONFIRMED - CatchPulse blocking is disabled."
CatchPulse UI showing device at risk and critical features not in force
Figure 5 - CatchPulse UI after the bypass: the product reports a risk state and indicates that critical features are not in force.
CatchPulse UI showing device protected after recovery
Figure 6 - Post-test recovery state: CatchPulse later reports the device as protected after the test system is restored.

4. Root cause analysis

4.1 NULL DACL on \SAAppWhitelistingPort

During driver initialization, ports are created through a helper where one argument controls whether the admin-only default security descriptor is retained. For \SAAppWhitelistingPort, the observed setting causes the helper to replace the DACL with NULL. A NULL DACL means any local process can connect to the port regardless of privilege.

Port namea9Effective access control
\SAAppCtlPort1Admin-only
\SAAppCtlCommandPort1Admin-only
\SAAppWhitelistingPort0NULL DACL - unrestricted
\SAAppCtlNotifierPort0NULL DACL - unrestricted

4.2 Missing privilege check on cmd=6

The dispatcher protects several privileged commands by calling a token-checking gate, but cmd=6 is not routed through that gate. The only observed validation is that three date fields satisfy the arithmetic identity start + duration == end. That condition is trivial to satisfy using past license dates, after which the handler writes the supplied value to HKLM\SYSTEM\CurrentControlSet\Services\SAPlus\ExpiryDate.

Related issue: cmd=12 has the same structural defect: it is dispatched without the same privilege gate and writes to a machine-wide registry location. Although the observed cmd=12 target is a scan-speed tuning value rather than the enforcement-critical ExpiryDate, it should be fixed together with cmd=6 to address the underlying authorization flaw.

5. Impact assessment

5.1 Security impact

  • Integrity impact is high: previously denied executables can run after the bypass.
  • Availability of the security control is high impact: the core whitelisting function is disabled rather than only misclassifying one file.
  • Confidentiality impact is not directly demonstrated, but successful execution of untrusted code can become an enabling step for later data access by malware or a malicious local actor.
  • No administrator rights are required. The vulnerability crosses the expected boundary between ordinary local user and product policy control.
  • The exploit path can run through Microsoft-signed MSBuild.exe, reducing the effectiveness of policies that only block PowerShell or unsigned/custom executables.

5.2 Persistence and recovery impact

The bypass was not fully reversible by sending a valid future ExpiryDate and attempting to restart the service. The service is NOT_STOPPABLE, and the kernel driver state remains loaded after the restore attempt. The observed operational consequence is that a reboot or equivalent driver reload is required to restore enforcement.

If the forged ExpiryDate remains in the registry, enforcement can re-enter the trust-all state within minutes of reboot. On cloud-connected systems, the vendor cloud check-in was observed restoring the correct ExpiryDate after approximately 58 minutes. On offline or air-gapped systems, the bypass may persist indefinitely until the registry value is corrected and the driver state is reset.

Defender risk

A defender who only corrects the registry value may believe protection has been restored while the kernel enforcement state remains non-blocking. Recovery guidance should explicitly require registry correction plus reboot/driver reload and validation that a previously blocked canary executable is blocked again.

6. Proof-of-concept validation summary

The proof of concept was validated during coordinated disclosure. Proof-of-concept code was provided privately and is intentionally not being released publicly.

6.1 PowerShell ISE validation

Validation used a known-blocked canary executable, test_bypass.exe, from a standard-user context.

  • Before validation, test_bypass.exe was blocked by CatchPulse as expected.
  • The validation was performed from a standard-user context.
  • The script connected to \SAAppWhitelistingPort and received HRESULT 0x00000000 with kernel outBuf status 0x00000000.
  • After validation, the same test_bypass.exe executed without being blocked.
  • The observed behavior confirms an end-to-end application-whitelisting enforcement bypass from a standard user context.

7. Remediation recommendations

7.1 Apply admin-only DACL to \SAAppWhitelistingPort

Change the a9 argument for \SAAppWhitelistingPort from 0 to 1 in the DriverEntry port-creation path so the default admin-only security descriptor is retained. Apply the same hardening to \SAAppCtlNotifierPort unless unrestricted access is explicitly required and safe by design.

7.2 Add explicit privilege checks to cmd=6 and cmd=12

The dispatcher should apply the same privilege gate used by commands 2, 3, 10, and 14 before allowing cmd=6 or cmd=12 to write machine-wide state. The command handler should fail closed if the caller is not SYSTEM, LocalService, NetworkService, an administrator, or another explicitly authorized principal.

7.3 Recovery and detection guidance

  • Monitor unexpected writes to HKLM\SYSTEM\CurrentControlSet\Services\SAPlus\ExpiryDate, especially writes resulting in past dates or all-zero values.
  • Monitor service logs for License is expired / trust all events occurring shortly after boot or outside legitimate license transitions.
  • Treat registry-only correction as insufficient. Recovery should include correcting the registry value, rebooting/reloading the driver, and validating that a known-blocked canary executable is blocked again.
  • Review allow-rules for MSBuild.exe and similar LOLBAS executables as a temporary risk-reduction step, but do not rely on policy restrictions as the primary fix.

8. Timeline

DateEvent
2026-06-23Vulnerability reported.
2026-08-06Public disclosure.