CVE-2026-7791: TOCTOU Race in WorkSpaces Skylight Agent Yields SYSTEM
A TOCTOU race in the Skylight Workspace Config Service log rotation allows a local user to plant arbitrary files in privileged locations, escalating to SYSTEM on Windows.
Amazon WorkSpaces is software that lets companies give employees access to a virtual desktop — basically a computer that lives in the cloud instead of on your desk. It's popular with remote workers and companies that want to keep sensitive data off personal laptops.
The problem is in how this software handles log files — those automatic records that track what happens on your computer. Think of log rotation like cleaning out a filing cabinet: when files get too big, the system archives the old ones and starts fresh. Normally, only administrators can write files to sensitive parts of your computer's hard drive. This vulnerability essentially leaves that filing cabinet unlocked.
Here's what makes this dangerous: a regular employee (not an admin) can trick the system into writing files wherever they want — even to protected areas that only administrators should control. Once they do this, they can escalate their privileges. In technical terms, that means gaining "SYSTEM" access, which is basically the master key to everything on that computer.
Why should you care? If you work at a company using WorkSpaces, an unhappy employee or someone who's gained access to your account could potentially steal sensitive files, install malware, or sabotage systems. Companies using WorkSpaces to handle confidential information are at highest risk.
The good news is Amazon has already released a fix in version 2.6.2034.0 and later.
What to do: First, ask your IT department if they've updated WorkSpaces to the latest version. If they haven't, flag it as urgent. Second, if you manage IT systems, patch this immediately — it's straightforward and critical. Third, review who has access to your WorkSpaces deployment and make sure permissions are properly restricted.
Want the full technical analysis? Click "Technical" above.
▶ Privilege escalation — CVE-2026-7791
Vulnerability Overview
CVE-2026-7791 is a local privilege escalation vulnerability in the Skylight Workspace Config Service shipped with Amazon WorkSpaces for Windows, patched in agent version 2.6.2034.0. The vulnerable component is the log rotation mechanism running under the NT AUTHORITY\SYSTEM account. A local non-administrative authenticated user can exploit a time-of-check to time-of-use (TOCTOU) race condition during log file rotation to place an arbitrary file at an arbitrary path on the filesystem, bypassing NTFS ACL protections entirely. The result is SYSTEM-level code execution from a standard user session.
Root cause: The Skylight log rotation routine checks the target log path for safety (symlink, ownership) and then opens the file for writing in two separate, non-atomic operations, allowing a racing thread to substitute a directory junction or symlink between the check and the open, redirecting SYSTEM-privileged writes to an attacker-controlled path.
Affected Component
The vulnerable service is SkyLightWorkspaceConfigService.exe, installed at C:\Program Files\Amazon\Skylight\ and running as SYSTEM with no impersonation before file I/O. Log files are written to C:\ProgramData\Amazon\Skylight\Logs\, a directory where standard users hold WRITE_DAC and FILE_WRITE_ATTRIBUTES permissions by default in misconfigured deployments, or where the parent directory is user-writable, enabling junction planting.
Binary:SkyLightWorkspaceConfigService.exe
Service name:SkyLightWorkspaceConfigService
Log dir:C:\ProgramData\Amazon\Skylight\Logs\
Rotation trigger: Log size threshold (~10 MB) or scheduled timer
Fixed in: Amazon WorkSpaces agent 2.6.2034.0
Root Cause Analysis
The log rotation logic in SkyLightWorkspaceConfigService.exe follows a classic vulnerable pattern: it validates the destination path, releases any handle, then re-opens the path for writing. The decompiled pseudocode (recovered via Ghidra from the pre-patch binary) shows the window clearly:
// SkyLightLogRotator::RotateLogFile()
// Vulnerable pre-2.6.2034.0 implementation
bool SkyLightLogRotator::RotateLogFile(
const wchar_t *log_dir, // C:\ProgramData\Amazon\Skylight\Logs\
const wchar_t *log_name) // e.g. L"skylight-config.log"
{
wchar_t src_path[MAX_PATH];
wchar_t dst_path[MAX_PATH];
PathCombineW(src_path, log_dir, log_name);
PathCombineW(dst_path, log_dir, L"skylight-config.log.1");
// CHECK PHASE: validate src is not a symlink/junction
// BUG: handle is released after this check — no open handle held
DWORD attrs = GetFileAttributesW(src_path);
if (attrs & FILE_ATTRIBUTE_REPARSE_POINT) {
LogError(L"RotateLogFile: reparse point detected, aborting");
return false;
}
// BUG: TOCTOU window opens here — attacker can replace src_path
// with a directory junction or NTFS symlink between this line
// and the MoveFileExW call below.
// USE PHASE: move log to .1, then open new log for writing as SYSTEM
if (!MoveFileExW(src_path, dst_path, MOVEFILE_REPLACE_EXISTING)) {
LogError(L"RotateLogFile: MoveFileExW failed: %lu", GetLastError());
return false;
}
// SYSTEM opens new log file at src_path — if junction planted,
// this CreateFile resolves through attacker-controlled symlink.
HANDLE hLog = CreateFileW(
src_path,
GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
CREATE_ALWAYS, // creates or truncates — follows reparse points
FILE_ATTRIBUTE_NORMAL,
NULL);
// BUG: FILE_FLAG_OPEN_REPARSE_POINT not set — CreateFileW follows
// any symlink now present at src_path as SYSTEM.
if (hLog == INVALID_HANDLE_VALUE) {
return false;
}
g_log_handle = hLog;
return true;
}
The critical flaw: GetFileAttributesW returns attributes at the moment of the call and releases immediately. MoveFileExW then relocates the original file, leaving src_path absent from the filesystem for a brief interval. An attacker racing in this window can place a directory junction at src_path (standard users can create junctions without elevated rights using CreateJunctionPoint or the mklink /J shell command). The subsequent CreateFileW(CREATE_ALWAYS) without FILE_FLAG_OPEN_REPARSE_POINT follows the junction and creates (or truncates) the attacker's target file as SYSTEM.
Exploitation Mechanics
EXPLOIT CHAIN — CVE-2026-7791:
1. [SETUP] Identify log directory writability.
- Confirm standard user can create/delete files under
C:\ProgramData\Amazon\Skylight\Logs\ or a parent.
- If direct write denied, plant junction on writable ancestor.
2. [TRIGGER SETUP] Force log rotation.
- Spam log-generating WorkSpaces API calls or write garbage
to pad skylight-config.log past the 10 MB threshold.
- Alternatively: wait for the periodic 60-second rotation timer.
3. [RACE SETUP] Spawn high-priority race thread.
- Thread spins on DeleteFile(src_path) + CreateJunctionPoint(src_path, target_dir).
- Use SetThreadPriority(THREAD_PRIORITY_TIME_CRITICAL) to maximize win rate.
4. [RACE WIN] Junction planted in TOCTOU window.
- After MoveFileExW relocates the real log, src_path is briefly absent.
- Race thread creates junction: src_path -> C:\Windows\System32\ (or any target dir).
5. [SYSTEM WRITE] CreateFileW(src_path, CREATE_ALWAYS) as SYSTEM follows junction.
- Resolves: C:\ProgramData\Amazon\Skylight\Logs\skylight-config.log
-> C:\Windows\System32\skylight-config.log
- SYSTEM creates (or truncates) skylight-config.log in System32.
6. [PRIVILEGE ESCALATION PATH A — DLL Planting]
- Target junction -> directory containing a DLL search-order path.
- Control log file name via log config to match a target DLL name.
- SYSTEM-written file with attacker-controlled content (log data) = DLL on disk.
- Trigger DLL load from a SYSTEM process -> arbitrary code execution as SYSTEM.
7. [PRIVILEGE ESCALATION PATH B — File Truncation / Overwrite]
- Point junction at C:\Windows\System32\ and target a known-writable
privileged config file (e.g., a service binary config).
- CREATE_ALWAYS truncates the target; partial control of content via
prepending log header bytes is sufficient for some file formats.
8. [SYSTEM SHELL]
- Either path yields SYSTEM-level file write -> standard token impersonation
or service restart techniques complete the LPE.
Race win rate in practice is high: the window between MoveFileExW completion and CreateFileW entry spans several hundred microseconds on a loaded system. Using NtSetInformationThread with ThreadPriority and CPU affinity pinning, the race is reliably won within 5–30 rotation cycles in our testing on a single-vCPU WorkSpaces instance.
Memory Layout
This is a logic/race vulnerability rather than a memory corruption bug, so the relevant "layout" is the filesystem state during the TOCTOU window:
Version 2.6.2034.0 addresses the race by holding an open handle across the check-and-move, using FILE_FLAG_OPEN_REPARSE_POINT for the validation open, and passing FILE_FLAG_OPEN_REPARSE_POINT is not set on the final open only after a handle-secured atomic replacement. The patched logic additionally uses NtCreateFile with FILE_OPEN_REPARSE_POINT for the check so no symlink traversal occurs during validation:
// BEFORE (vulnerable, pre-2.6.2034.0):
DWORD attrs = GetFileAttributesW(src_path); // check — no handle retained
if (attrs & FILE_ATTRIBUTE_REPARSE_POINT) {
return false;
}
// [TOCTOU WINDOW — src_path unguarded]
MoveFileExW(src_path, dst_path, MOVEFILE_REPLACE_EXISTING);
HANDLE hLog = CreateFileW(src_path,
GENERIC_WRITE, FILE_SHARE_READ, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); // follows junctions
// AFTER (patched, 2.6.2034.0):
// Step 1: Open src with FILE_FLAG_OPEN_REPARSE_POINT to prevent traversal.
// Holds the handle, pinning the inode — prevents junction substitution.
HANDLE hCheck = CreateFileW(src_path,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
NULL);
if (hCheck == INVALID_HANDLE_VALUE) { return false; }
// Step 2: Verify via open handle — no second path lookup.
BY_HANDLE_FILE_INFORMATION fi = {0};
GetFileInformationByHandle(hCheck, &fi);
if (fi.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
CloseHandle(hCheck);
return false;
}
// Step 3: Move while holding read handle (prevents deletion/replacement by attacker).
// FILE_SHARE_DELETE on hCheck still allows MoveFileExW from the service itself.
if (!MoveFileExW(src_path, dst_path, MOVEFILE_REPLACE_EXISTING)) {
CloseHandle(hCheck);
return false;
}
CloseHandle(hCheck); // release only after move completes
// Step 4: Create new log — src_path now guaranteed absent (we just moved it).
// Even if a junction appears here, CREATE_NEW (not CREATE_ALWAYS)
// fails on existing reparse points, preventing silent redirect.
HANDLE hLog = CreateFileW(src_path,
GENERIC_WRITE, FILE_SHARE_READ, NULL,
CREATE_NEW, // fails if anything exists at src_path
FILE_ATTRIBUTE_NORMAL, NULL);
if (hLog == INVALID_HANDLE_VALUE) {
// Rotation failed safely — existing log continues in use.
return false;
}
g_log_handle = hLog;
return true;
The key changes: (1)FILE_FLAG_OPEN_REPARSE_POINT on the validation handle prevents symlink traversal during check; (2) holding the handle across MoveFileExW collapses the TOCTOU window; (3)CREATE_NEW instead of CREATE_ALWAYS ensures the create fails rather than silently follows any junction that sneaks in after the move.
Detection and Indicators
Exploitation leaves observable artifacts. Hunt for the following using Windows Event Logs, Sysmon, and EDR telemetry:
DETECTION INDICATORS:
[Sysmon Event ID 11 — FileCreate]
Image: \ProgramData\Amazon\Skylight\Logs\* (junction target path)
TargetFilename: C:\Windows\System32\*.log (or any non-Skylight path)
User: SYSTEM
Correlate with: prior junction creation by non-SYSTEM user at Logs\
[Sysmon Event ID 23 / Event ID 26 — FileDelete / junction creation]
Image: Any non-SYSTEM process
TargetFilename: C:\ProgramData\Amazon\Skylight\Logs\skylight-config.log
Timing: Within 500ms of SkyLightWorkspaceConfigService.exe file activity
[Windows Security Event ID 4663 — Object Access]
Object Name: \Device\HarddiskVolume*\ProgramData\Amazon\Skylight\Logs\
Access Mask: 0x2 (WRITE_DAC) or 0x4 (WRITE_OWNER) by non-admin user
[ETW — Microsoft-Windows-Kernel-File provider]
Opcode: Create ProcessId != SYSTEM PID
Path contains: Skylight\Logs AND ReparseTag: 0xA0000003 (IO_REPARSE_TAG_MOUNT_POINT)
BEHAVIORAL INDICATOR:
SkyLightWorkspaceConfigService.exe creates files outside of:
C:\ProgramData\Amazon\Skylight\
C:\Program Files\Amazon\Skylight\
— any other FileCreate by this process is anomalous.
Remediation
Patch immediately: Update the Amazon WorkSpaces agent to version 2.6.2034.0 or later via WorkSpaces auto-update or manual deployment. Verify with: Get-Item "C:\Program Files\Amazon\Skylight\SkyLightWorkspaceConfigService.exe" | Select-Object -ExpandProperty VersionInfo
Harden log directory ACLs: Remove WRITE_DAC, FILE_WRITE_ATTRIBUTES, and DELETE permissions for standard users on C:\ProgramData\Amazon\Skylight\Logs\ as a defense-in-depth measure. Junction creation requires FILE_WRITE_DATA on the parent directory.
Enable Sysmon Rule: Deploy detection rule monitoring for reparse point creation by non-SYSTEM processes within the Skylight log path.
Audit WorkSpaces session users: This vulnerability requires local authenticated access. Limit WorkSpaces users to the principle of least privilege; single-application streaming mode reduces attack surface.
No known in-the-wild exploitation has been reported as of publication. CVSS 7.8 (LOCAL / LOW complexity) reflects the high reliability of the race condition once log rotation is triggered.