Back to Intelligence

CVE-2026-91813: Foxit PDF Reader FoxitUpdater Race Condition Privilege Escalation — Detection and Remediation Guide

SA
Security Arsenal Team
September 24, 2026
10 min read

A newly published Zero Day Initiative advisory — ZDI-26-742 — discloses a race condition vulnerability in the FoxitUpdater component of Foxit PDF Reader that allows a local attacker to escalate privileges on affected systems. Tracked as CVE-2026-91813 and rated CVSS 7.8 (High), the flaw requires the attacker to already execute low-privileged code on the target — which is precisely the posture attackers hold after a phishing payload, malicious document, or commodity loader detonation. In other words: this is a textbook second-stage privilege escalation primitive sitting on endpoints across your enterprise right now.

Foxit PDF Reader is deployed broadly as a lightweight Acrobat alternative — frequently in cost-sensitive environments, embedded in golden images, and bundled by OEMs. The updater component runs with elevated privileges by design, making it a high-value target for local privilege escalation (LPE). Defenders should treat this advisory as actionable immediately: inventory Foxit deployments, constrain updater behavior, deploy behavioral detections, and track Foxit's patch release.

Technical Analysis

Affected Component and Platform

  • Product: Foxit PDF Reader (Windows)
  • Component: FoxitUpdater (the auto-update service/executable, typically FoxitUpdater.exe, commonly residing under the Foxit installation directory such as C:\Program Files (x86)\Foxit Software\Foxit PDF Reader\ or invoked through a scheduled task / service with SYSTEM-level privileges)
  • Advisory: ZDI-26-742 (http://www.zerodayinitiative.com/advisories/ZDI-26-742/)
  • CVE: CVE-2026-91813
  • CVSS: 7.8 (High) — consistent with a local privilege escalation vector (local attack vector, low complexity, no user interaction beyond existing code execution, high impact to confidentiality/integrity/availability)
  • Attack class: Race condition (CWE-362 / CWE-367 time-of-check time-of-use style flaws are the common root cause in privileged updater LPEs)

How the Vulnerability Works (Defender's Perspective)

Privileged updater components are one of the most reliably exploitable LPE surfaces on Windows, and the pattern here follows a well-worn playbook. A race condition in an updater that runs as SYSTEM typically manifests in one of these forms:

  1. TOCTOU on file validation: The updater checks a file (signature, hash, path) and then acts on it a moment later. An attacker who can win the race swaps the validated file for attacker-controlled content between the check and the use.
  2. Insecure temp/staging directory handling: The updater writes update payloads, scripts, or DLLs to a world-writable staging location, then executes or loads them as SYSTEM. An attacker replaces or hijacks the file in the window between write and execution.
  3. Symbolic link / junction / hardlink abuse: The attacker plants a reparse point so that when the privileged updater deletes, moves, or writes a file, the operation is redirected to an arbitrary location — e.g., overwriting a DLL loaded by a SYSTEM service or dropping a file into C:\Windows\System32.

The exploitation requirement is important and limits the blast radius: the attacker must already have low-privileged code execution on the host. This is not a remote exploit. But in real intrusion chains, that precondition is nearly always met — initial access brokers, phishing loaders, and post-exploitation frameworks all land as the user first, then hunt for exactly this class of bug to pivot from user context to SYSTEM. CVSS 7.8 undersells the operational risk in environments where Foxit is widespread and local admin is tightly controlled: this is the rung on the ladder that breaks your least-privilege model.

Exploitation Status

At the time of writing, the advisory is a coordinated ZDI disclosure. ZDI advisories of this class are typically published with a patch or imminent vendor fix, and technical details sufficient for offensive reproduction often follow public disclosure within days to weeks. There is no confirmed in-the-wild exploitation or CISA KEV listing associated with CVE-2026-91813 at this time — but race-condition LPEs in updaters have historically been weaponized quickly once PoCs circulate, because the exploitation technique is generic and well-documented in the offensive community. Treat the window between disclosure and patch deployment as your exposure window.

Detection & Response

Because exploitation requires local code execution, your detection strategy should focus on behavioral anomalies around the FoxitUpdater process and its file operations, not on static indicators — there are no IOCs to block here, only behaviors to catch.

Sigma Rules

YAML
---
title: FoxitUpdater Spawning Unexpected Child Process
id: 3f8a2c71-9b4d-4e5a-a1c6-7d2e8f901234
status: experimental
description: Detects FoxitUpdater.exe spawning command interpreters, scripting engines, or unsigned executables — consistent with post-race-condition payload execution at SYSTEM privilege following CVE-2026-91813 exploitation.
references:
  - http://www.zerodayinitiative.com/advisories/ZDI-26-742/
  - https://attack.mitre.org/techniques/T1068/
author: Security Arsenal
date: 2026/01/15
tags:
  - attack.privilege_escalation
  - attack.t1068
logsource:
  category: process_creation
  product: windows
detection:
  selection_parent:
    ParentImage|endswith: '\FoxitUpdater.exe'
  selection_child:
    Image|endswith:
      - '\cmd.exe'
      - '\powershell.exe'
      - '\pwsh.exe'
      - '\wscript.exe'
      - '\cscript.exe'
      - '\mshta.exe'
      - '\rundll32.exe'
      - '\regsvr32.exe'
      - '\wmic.exe'
  condition: selection_parent and selection_child
falsepositives:
  - Rare; legitimate Foxit updates may invoke installer subprocesses but not interactive interpreters
level: high
---
title: File Write by FoxitUpdater to Sensitive System Locations
id: 8c1d4e92-5a3b-4f67-b2d8-9e1a3c5f7b60
status: experimental
description: Detects FoxitUpdater.exe writing executable content into Windows system directories — a strong indicator of symlink/hardlink redirection or file-swap race condition exploitation (CVE-2026-91813) achieving arbitrary file write as SYSTEM.
references:
  - http://www.zerodayinitiative.com/advisories/ZDI-26-742/
  - https://attack.mitre.org/techniques/T1068/
author: Security Arsenal
date: 2026/01/15
tags:
  - attack.privilege_escalation
  - attack.t1068
logsource:
  category: file_event
  product: windows
detection:
  selection_image:
    Image|endswith: '\FoxitUpdater.exe'
  selection_target:
    TargetFilename|contains:
      - '\Windows\System32\'
      - '\Windows\SysWOW64\'
      - '\Windows\Sysnative\'
  selection_ext:
    TargetFilename|endswith:
      - '.dll'
      - '.exe'
      - '.sys'
      - '.bat'
      - '.ps1'
  condition: selection_image and selection_target and selection_ext
falsepositives:
  - Extremely rare; Foxit updates should never stage payloads into System32
level: critical

KQL — Microsoft Sentinel / Defender for Endpoint

The following hunt looks for the behavioral chain: low-privileged processes interacting with FoxitUpdater staging paths, followed by FoxitUpdater spawning unusual children or touching privileged locations. Run it as a 7-day lookback hunt, then convert to an analytics rule with a narrower window.

KQL — Microsoft Sentinel / Defender
let Lookback = 7d;
let FoxitProc = dynamic(["foxitupdater.exe"]);
// Stage 1: FoxitUpdater spawning suspicious child processes
let SuspiciousChildren = DeviceProcessEvents
| where TimeGenerated > ago(Lookback)
| where InitiatingProcessFileName in~ (FoxitProc)
| where FileName in~ ("cmd.exe","powershell.exe","pwsh.exe","wscript.exe","cscript.exe","mshta.exe","rundll32.exe","regsvr32.exe","wmic.exe","msiexec.exe")
| project ChildTime=TimeGenerated, DeviceId, DeviceName, ChildProc=FileName, ChildCmd=ProcessCommandLine, AccountName, InitiatingProcessCommandLine;
// Stage 2: FoxitUpdater writing executable content to system directories
let SuspiciousWrites = DeviceFileEvents
| where TimeGenerated > ago(Lookback)
| where InitiatingProcessFileName in~ (FoxitProc)
| where FolderPath has_any ("\\Windows\\System32\\","\\Windows\\SysWOW64\\")
| where FileName endswith_any (".dll",".exe",".sys",".bat",".ps1")
| project WriteTime=TimeGenerated, DeviceId, DeviceName, TargetPath=FolderPath, ActionType, InitiatingProcessCommandLine;
// Stage 3: Non-SYSTEM processes creating links/writing into Foxit install or staging dirs (race setup)
let RaceSetup = DeviceFileEvents
| where TimeGenerated > ago(Lookback)
| where FolderPath has ("Foxit")
| where ActionType in~ ("FileCreated","FileModified","FileRenamed")
| where InitiatingProcessFileName !in~ (FoxitProc) and InitiatingProcessFileName !endswith "foxitpdfreader.exe"
| where InitiatingProcessAccountSid !endswith "-500" // exclude local admin churn; tune per environment
| project SetupTime=TimeGenerated, DeviceId, DeviceName, SetupProc=InitiatingProcessFileName, SetupCmd=InitiatingProcessCommandLine, FolderPath, FileName;
SuspiciousChildren
| union SuspiciousWrites
| union RaceSetup
| order by DeviceName asc

Velociraptor VQL

Use this artifact to sweep the fleet for live FoxitUpdater execution context — who is running it, from where, and with what command line — plus any concurrent processes interacting with Foxit paths. An updater running from an unexpected path, or under a non-SYSTEM/non-standard context, is a red flag.

VQL — Velociraptor
-- CVE-2026-91813 hunt: FoxitUpdater execution context and Foxit-path interaction
SELECT Pid, Ppid, Name, CommandLine, Exe, Username, CreateTime
FROM pslist()
WHERE Name =~ '(?i)foxitupdater'
   OR Exe =~ '(?i)foxit'
   OR CommandLine =~ '(?i)foxitupdater'

For file-artifact triage on a suspect host, enumerate the Foxit installation and any staging/temp directories for recently created executables or link artifacts:

VQL — Velociraptor
-- Recent executable artifacts under Foxit paths and common updater staging dirs
SELECT FullPath, Size, Mtime, Ctime
FROM glob(globs=[
  'C:/Program Files*/Foxit Software/**/*.exe',
  'C:/Program Files*/Foxit Software/**/*.dll',
  'C:/ProgramData/Foxit*/**/*',
  'C:/Users/*/AppData/**/Foxit*/**/*.exe'
])
WHERE Mtime > timestamp(epoch=1704067200)  -- 2026-01-01; adjust to your hunt window
ORDER BY Mtime DESC

Verification and Hardening Script

This PowerShell script inventories Foxit PDF Reader installations, identifies the FoxitUpdater binary and its execution context, and reports patch posture so you can prioritize remediation. Run it via your RMM or as an Intune/SCCM compliance script across the fleet.

PowerShell
# CVE-2026-91813 - Foxit FoxitUpdater race condition LPE: inventory & posture check
$results = @()

# Locate Foxit PDF Reader installs via registry uninstall hives
$uninstallPaths = @(
  'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*',
  'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*'
)
$foxit = Get-ItemProperty $uninstallPaths -ErrorAction SilentlyContinue |
  Where-Object { $_.DisplayName -match 'Foxit' } |
  Select-Object DisplayName, DisplayVersion, InstallLocation, Publisher

foreach ($app in $foxit) {
  $updaterPath = $null
  if ($app.InstallLocation) {
    $candidate = Join-Path $app.InstallLocation 'FoxitUpdater.exe'
    if (Test-Path $candidate) { $updaterPath = $candidate }
  }
  if (-not $updaterPath) {
    $found = Get-ChildItem 'C:\Program Files','C:\Program Files (x86)' -Recurse -Filter 'FoxitUpdater.exe' -ErrorAction SilentlyContinue | Select-Object -First 1
    if ($found) { $updaterPath = $found.FullName }
  }

  $updaterVersion = $null
  if ($updaterPath) {
    $updaterVersion = (Get-Item $updaterPath).VersionInfo.FileVersion
  }

  # Check for a Foxit update scheduled task running as SYSTEM (attack surface confirmation)
  $tasks = Get-ScheduledTask -ErrorAction SilentlyContinue | Where-Object { $_.TaskName -match 'Foxit' }
  $taskInfo = $tasks | ForEach-Object { "$($_.TaskName) [$($_.Principal.UserId)]" }

  $results += [pscustomobject]@{
    Hostname       = $env:COMPUTERNAME
    Product        = $app.DisplayName
    Version        = $app.DisplayVersion
    UpdaterPath    = $updaterPath
    UpdaterVersion = $updaterVersion
    UpdateTasks    = ($taskInfo -join '; ')
    ActionRequired = 'Apply vendor patch for CVE-2026-91813 when released; see ZDI-26-742'
  }
}

if ($results.Count -eq 0) {
  Write-Output "No Foxit products detected on $env:COMPUTERNAME"
} else {
  $results | Format-List
  $results | Export-Csv -Path "$env:TEMP\foxit_cve-2026-91813_inventory.csv" -NoTypeInformation
}

# Interim hardening: if patch is unavailable, consider disabling the auto-update scheduled task
# to reduce the window in which the privileged updater acts on attacker-influenceable files.
# Uncomment ONLY after change-control approval (this disables auto-updates):
# Get-ScheduledTask | Where-Object { $_.TaskName -match 'Foxit.*(Update|Updater)' } | Disable-ScheduledTask

Remediation

  1. Apply the vendor fix immediately upon release. ZDI-26-742 is a coordinated disclosure; obtain the patched build from Foxit's official security bulletins page (https://www.foxit.com/support/security-bulletins.html) and the ZDI advisory (http://www.zerodayinitiative.com/advisories/ZDI-26-742/). Confirm the exact fixed version against Foxit's bulletin rather than third-party aggregators, and push it via your software deployment tooling. Verify the deployed version with the script above.
  2. Inventory first. You cannot patch what you cannot see. Foxit frequently arrives via OEM bundles, user self-installs, and portable packages that evade traditional software metering. Sweep for FoxitUpdater.exe and Foxit registry artifacts fleet-wide.
  3. Interim mitigation while awaiting patch: If your risk tolerance requires it before the patch lands, disable the Foxit auto-update scheduled task/service (see commented section of the script) and enforce updates centrally. This removes the recurring privileged trigger the race condition depends on. Document the trade-off: you are exchanging a latent LPE for managed update cadence.
  4. Reduce the precondition. Exploitation requires low-privileged code execution. This is where your existing controls earn their keep: application control (WDAC/AppLocker) to constrain user-writable payload execution, attack surface reduction rules, and email/browser isolation all shrink the pool of hosts where an attacker can even attempt this escalation.
  5. Deploy the detections above. The Sigma rules and KQL hunt target the exploitation behavior — child processes, system-directory writes, staging-path tampering — which remains valid regardless of the exact PoC mechanics. Convert the KQL into a scheduled analytics rule after baseline tuning.
  6. Enforce least privilege as compensating control. Users running without local admin limit (but do not eliminate) the post-exploitation value of a SYSTEM-level LPE; pair this with LAPS-managed local admin and tiered administration.
  7. Track KEV and threat intel. Monitor the CISA Known Exploited Vulnerabilities catalog and ZDI/Foxit channels. If CVE-2026-91813 gains confirmed in-the-wild exploitation or a public PoC, escalate patch priority to emergency change windows — race-condition LPEs move from disclosure to weaponization fast.

Bottom Line

CVE-2026-91813 is not an internet-facing emergency — but it is exactly the kind of reliable local escalation that turns a contained phishing detonation into full host compromise. The fix is straightforward: know where Foxit lives in your environment, watch FoxitUpdater's behavior until the patch is deployed, and ship the vendor update the day it drops. The organizations that get hurt by updater LPEs are almost never the ones that didn't know — they're the ones that couldn't find all their installs in time.

Related Resources

Security Arsenal Penetration Testing Services AlertMonitor Platform Book a SOC Assessment vulnerability-management Intel Hub

Is your security operations ready?

Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.