
Technical write-up and proof-of-concept for CVE-2026-8069, a local privilege escalation in Acer NitroSense and PredatorSense services, exploiting a named pipe to execute arbitrary code as SYSTEM.
Acer NitroSense and PredatorSense 3.x installed a Windows service called PSSvc that exposed a custom named-pipe protocol to local users. One protocol command accepted a caller-controlled executable path, duplicated the token of winlogon.exe, and started that executable as NT AUTHORITY\SYSTEM.
The path restriction in the vulnerable service was a substring test. A path that began inside the service directory and then used ..\ components passed the test but resolved somewhere else. Combined with the pipe's permissive access control and the absence of caller authorization, this allowed a standard local user to obtain a SYSTEM process.
Acer assigned CVE-2026-8069, published fixed releases, and credited Artem Domarev of the University of Hradec Králové in its security advisory.
This article focuses on the process-creation/LPE path. Acer's advisory also describes arbitrary file deletion, which was outside the scope of this validation.
The choice of research direction was also influenced by a public analysis of OEM software published by Leon Jacobs of SensePost. That work documented vulnerabilities in ASUS DriverHub, MSI Center, Acer Control Centre, and Razer Synapse 4 (Jacobs, 2025). It reinforced the idea that vendor-supplied hardware utilities can expose a meaningful and underexplored attack surface. Rather than revisiting Acer Control Centre, I extended the investigation to a different Acer product family: NitroSense and PredatorSense.
| Item | Result |
|---|---|
| CVE | CVE-2026-8069 |
| Vulnerable component tested | PSSvc.exe 3.1.3052.0, signed by Acer Incorporated |
| Service identity | LocalSystem |
| IPC endpoint | \\.\pipe\predatorsense_service_namedpipe |
| Vulnerable command | 0x0007 |
| Required attacker access | Authenticated local user able to run a program |
| User interaction | None |
| Result | Arbitrary executable launched as NT AUTHORITY\SYSTEM |
| NVD CVSS v3.1 | 7.8 High — AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H |
| Fixed releases | PredatorSense 3.00.3198; NitroSense 3.01.3056 |
The exploitation chain is short:
authenticated local user
│
▼
permissive PSSvc named pipe
│ custom command 0x0007
▼
substring-only path check
│ service-dir\..\..\..\Windows\System32\cmd.exe
▼
duplicate active-session winlogon.exe token
│
▼
CreateProcessAsUserW → NT AUTHORITY\SYSTEM
There is an inconsistency in the public wording. Acer's page says that NitroSense versions "before 3.01.3052" are affected, yet the vendor-signed PSSvc.exe version 3.1.3052.0 tested for this article is demonstrably vulnerable. The same page identifies NitroSense 3.01.3056 as the fixed release. The NVD applicability range also extends up to, but not including, 3.01.3056.
For PredatorSense, Acer's affected-version sentence stops before 3.00.3196, while the listed fixed release is 3.00.3198 and NVD uses the latter as the upper boundary.
The conservative operational rule is therefore simple: do not use the ambiguous "affected" sentence as a patch check. Upgrade to at least the fixed versions Acer names—PredatorSense 3.00.3198 or NitroSense 3.01.3056—or a newer model-compatible package.
The issue was reproduced with the original NitroSense package.
| Artifact | SHA-256 |
|---|---|
NitroSense_V3.01.3052_MSFT_SIGNED_20230420.zip | 947FB7C62665875450AFA9C9E7919D2B061ED8197C11B28D64781F121B30C157 |
NitroSense.msi | 6F9D405B6D2ADF2992C4E071453AD2C919A6DD38A89A31EF96EAFE81C50A745C |
Installed PSSvc.exe 3.1.3052.0 | 3BA836B6A5D95B55708E771B74F49098F58B096EF1F63C5CCAE355811E193A40 |
| PoC used for validation | 31BC81140BAB64A8B0CB70ACC1C2CF3CA84A7B00015E5610AC075DC50DCB0163 |
The PSSvc.exe Authenticode signature validated successfully and chained to Acer Incorporated. The MSI installed PSSvc as a demand-start, own-process service running as LocalSystem.
The NitroSense package installs:
SERVICE_NAME: PSSvc
DISPLAY_NAME: Predator Service
TYPE: WIN32_OWN_PROCESS
START_TYPE: DEMAND_START
ACCOUNT: LocalSystem
A SYSTEM service is not automatically vulnerable. The important question is whether a lower-privileged process can reach functionality that was designed under the assumption that its caller is trusted.
String analysis immediately exposed the IPC endpoint:
\\.\pipe\predatorsense_service_namedpipe
At 0x140014AD0, the service constructs the pipe and passes an explicit security descriptor to CreateNamedPipeW:
D:(A;OICI;GA;;;BG)(D;OICI;GA;;;AN)(A;OICI;GRGWGX;;;AU)(A;OICI;GA;;;BA)
This is worth correcting explicitly: the vulnerable build does not pass a NULL descriptor. It creates a permissive DACL.
| SID abbreviation | Principal | Effective permission in the SDDL |
|---|---|---|
BG | Built-in Guests | Generic All |
AN | Anonymous | Generic All denied |
AU | Authenticated Users | Generic Read, Write and Execute |
BA | Built-in Administrators | Generic All |
The AU ACE is enough for a normal authenticated user to open the pipe for reading and writing. The server does not then impersonate the client and perform an authorization decision before dispatching privileged commands.
The client thread at 0x14000ABB0 reads messages into a 512-byte buffer. It parses the first three bytes as a 16-bit command number and an 8-bit argument count. Each argument is length-prefixed:
Offset Size Meaning
0x00 2 command ID, little-endian
0x02 1 number of arguments
0x03 4 length of argument 0
0x07 n bytes of argument 0
... repeated DWORD length + value
String arguments are UTF-16LE. Integer arguments are little-endian DWORDs. The dispatcher accepts command IDs below 0x23 and uses them as indexes into a 35-entry function table at 0x140052C90.
The entry for command 0x0007 points to 0x14000BFD0.
Reduced to its security-relevant behavior, the handler looks like this:
int command_07(parsed_arguments *args)
{
wchar_t service_directory[MAX_PATH];
wchar_t *requested_path = args->wide_string[0];
uint32_t mode = args->dword[1];
GetModuleFileNameW(NULL, service_directory, MAX_PATH);
PathRemoveFileSpecW(service_directory);
if (wcsstr(requested_path, service_directory) != NULL)
return launch_with_selected_token(requested_path, mode);
return 0;
}
wcsstr answers only whether one string occurs inside another. It does not canonicalize a path, resolve dot segments, open a file, or prove that the final object remains under a trusted directory.
Assume the service is installed in:
C:\Program Files\Acer\NitroSense_Service
The following path contains that directory at offset zero, so wcsstr succeeds:
C:\Program Files\Acer\NitroSense_Service\..\..\..\WINDOWS\System32\cmd.exe
Windows resolves the dot segments to:
C:\WINDOWS\System32\cmd.exe
That is a classic canonicalization error: the validation is performed on one textual representation, while the sensitive operation consumes its normalized meaning.
The process-launch helper at 0x1400091F0 has a special branch when the second argument is 0x72 (decimal 114). It: