# Fortinet2Shell: FortiClient Local API Origin Validation Flaw Enables Code Execution via Malicious Websites (CVE-2026-121529)

> CVE-2026-121529 (Fortinet advisory FG-IR-26-194, CWE-346) is an origin validation error in a FortiClient local API endpoint that lets a malicious web page drive a local FortiClient service and execute code or commands on the victim's machine. Fortinet rates it Critical (CVSS 9.1), requires user interaction, and states it is not known to be exploited; fixes are in FortiClient 7.4.8 and 7.2.15.

- **Published:** 2026-11-11T22:46:41Z
- **Last reviewed:** 2026-11-11T22:46:41Z
- **Canonical:** https://intel.threadlinqs.com/threat/TL-2026-5802
- **Card image:** https://intel.threadlinqs.com/og/threat/TL-2026-5802.png
- **ID:** TL-2026-5802
- **Severity:** CRITICAL (CVSS 9.1)
- **Category:** VULNERABILITY
- **Status:** PATCHED
- **Detections:** 9 (1 shown free below) · **IOCs:** 10
- **CVEs:** CVE-2026-121529, CVE-2026-35616

## Description

Fortinet published advisory FG-IR-26-194 on 2026-11-10 for an origin validation error (CWE-346) in the local API component of FortiClient Mac, FortiClient Windows and FortiClient Windows PAM. Per the advisory, an unauthenticated remote attacker may execute unauthorized code or commands, and exploitation requires victim interaction. Fortinet lists the impact as escalation of privilege. The issue was reported externally by Kevin Joensen of Baldur Security under responsible disclosure, and the press coverage nicknamed it 'Fortinet2Shell'.

According to GBHackers' reporting, the root cause is a CORS misconfiguration: FortiClient runs a local service that wrongly trusts requests originating from web pages. When a victim visits an attacker-controlled page, script in that page sends cross-origin requests to the local FortiClient service, which accepts them and can be driven to run code on the host. The researcher reportedly states the exploit works reliably when FortiPAM is enabled. Note that this mechanism description comes from the press article; the Fortinet advisory itself only states the CWE-346 origin validation error and the code-execution impact.

Scoring: Fortinet's advisory lists CVSS v3 9.1 with vector AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H/E:P/RL:O/RC:C (the E:P/RL:O/RC:C temporal metrics are included). The NVD record (published 2026-11-10, status Received) carries Fortinet's CVSS 3.1 base vector AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H with base score 9.6, and a CISA SSVC assessment of Exploitation: none, Automatable: no, Technical Impact: total.

Affected: FortiClient Mac 7.4.0-7.4.7; FortiClient Windows 7.4.0-7.4.7 and 7.2.0-7.2.14; FortiClient Windows PAM 7.4.0-7.4.7 and 7.2.0-7.2.14. Not affected: version 8.0 of all three products and FortiClient Mac 7.2. Fixed in 7.4.8 and 7.2.15. Fortinet lists no workarounds and no virtual patch, so upgrading is the only remediation.

Exploitation status: Fortinet states the flaw is not known to be exploited, no public PoC or threat actor is named in the sources, and CISA SSVC lists exploitation as none. Researcher-reported Windows hunting indicators are a service listening on TCP port 9191 and a running FortiVRS.exe process; these identify exposed hosts rather than compromise. No file hashes, domains or IP addresses are published. Scoring caveat: the advisory lists 9.1 alongside a vector whose temporal metrics compute to roughly 8.6 and whose base metrics compute to 9.6 (NVD), so the score and vector are not mutually consistent; 9.1 is recorded as Fortinet's published figure. Separately, FortiClient EMS (a different product, CVE-2026-35616) was exploited in 2026 to deploy the EKZ infostealer; that is a distinct issue and is listed only as related context.

## MITRE ATT&CK

- T1203 Exploitation for Client Execution
- T1204.001 User Execution: Malicious Link
- T1059 Command and Scripting Interpreter

## Free detection (Splunk SPL, Microsoft KQL, Sigma)

**FortiClient Service Spawning Shell or Script Interpreter (CVE-2026-121529 Fortinet2Shell Exploitation)** (`TL-2026-5802-SPL-001`)

Detects cmd, PowerShell, script hosts or LOLBin interpreters launched by a FortiClient service process (FortiClient.exe, FortiVRS.exe, FortiESNAC.exe and related). CVE-2026-121529 (FG-IR-26-194, CWE-346) lets a malicious web page drive the FortiClient local API (TCP 9191) into running code or commands, so a FortiClient parent spawning an interpreter is the observable outcome of successful exploitation. Fortinet states no in-the-wild exploitation is known; this rule is behaviour-first, not signature based.

- **Languages:** Splunk SPL, Microsoft KQL, Sigma
- **ATT&CK:** T1203, T1059, T1059.001, T1059.003
- **Data sources:** sysmon, DeviceProcessEvents, windows_process_creation
- **Severity:** critical
- **Confidence:** high

### Splunk SPL

````spl
index=sysmon sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=1 earliest=-24h ParentImage IN ("*FortiClient.exe", "*FortiVRS.exe", "*FortiESNAC.exe", "*FCDBLog.exe", "*FortiSettings.exe", "*FortiTray.exe") Image IN ("*cmd.exe", "*powershell.exe", "*pwsh.exe", "*wscript.exe", "*cscript.exe", "*mshta.exe", "*rundll32.exe", "*regsvr32.exe")
```Any interpreter child of a FortiClient service process is anomalous; review CommandLine and User```
| stats count min(_time) as first_seen max(_time) as last_seen values(CommandLine) as command_lines values(User) as users values(IntegrityLevel) as integrity_levels by host ParentImage ParentCommandLine Image
| convert ctime(first_seen) ctime(last_seen)
````

### Microsoft KQL

```kql
let FortiParents = dynamic(["FortiClient.exe", "FortiVRS.exe", "FortiESNAC.exe", "FCDBLog.exe", "FortiSettings.exe", "FortiTray.exe"]);
DeviceProcessEvents
| where Timestamp > ago(24h)
| where InitiatingProcessFileName in~ (FortiParents)
| where FileName in~ ("cmd.exe", "powershell.exe", "pwsh.exe", "wscript.exe", "cscript.exe", "mshta.exe", "rundll32.exe", "regsvr32.exe")
| project Timestamp, DeviceName, AccountName, InitiatingProcessFileName, InitiatingProcessCommandLine, FileName, ProcessCommandLine, ProcessIntegrityLevel
| order by Timestamp desc
```

### Sigma

```yaml
title: FortiClient Service Spawning Shell or Script Interpreter
id: 7a1c3e52-9d4b-4f60-8a21-5e0b7c9d1f01
status: experimental
description: Detects an interpreter or script host spawned by a FortiClient service process, the observable result of CVE-2026-121529 (FG-IR-26-194) local API origin validation abuse via a malicious web page.
references:
    - https://fortiguard.fortinet.com/psirt/FG-IR-26-194
    - https://nvd.nist.gov/vuln/detail/CVE-2026-121529
author: Threadlinqs Team
date: 2026-11-11
tags:
    - attack.execution
    - attack.t1203
    - attack.t1059
    - attack.t1059.001
    - attack.t1059.003
    - cve.2026.121529
logsource:
    category: process_creation
    product: windows
detection:
    sel_parent:
        ParentImage|endswith: ['\FortiClient.exe', '\FortiVRS.exe', '\FortiESNAC.exe', '\FCDBLog.exe', '\FortiSettings.exe', '\FortiTray.exe']
    sel_child:
        Image|endswith: ['\cmd.exe', '\powershell.exe', '\pwsh.exe', '\wscript.exe', '\cscript.exe', '\mshta.exe', '\rundll32.exe', '\regsvr32.exe']
    condition: sel_parent and sel_child
falsepositives:
    - FortiClient installer, upgrade or EMS remediation scripts that legitimately launch cmd or PowerShell
    - Administrator-deployed FortiClient post-connect scripts
level: high

```

**Known false positives:**

- FortiClient upgrade or EMS remediation workflows that legitimately invoke cmd.exe or PowerShell
- Customer-defined FortiClient VPN connect or disconnect scripts

**Tuning notes:** Baseline 14 days of FortiClient-parented interpreter launches and exclude known ParentCommandLine plus CommandLine pairs from your deployment tooling. The exact vulnerable service binary is not published (FortiVRS.exe is the researcher-reported process), so confirm the binary names against your install. FortiClient Mac 7.4.x is also affected: mirror this logic with macOS process telemetry for FortiClient parenting sh, bash, zsh or osascript.

### 8 more detection rules (Splunk SPL, Microsoft KQL, Sigma), unlock with TL Creds

- Browser Connecting to FortiClient Local API on Loopback TCP 9191 (Fortinet2Shell Drive-by Trigger) (locked: unlock with TL Creds)
- FortiClient Process Dropping Executable or Script Into User-Writable Path (locked: unlock with TL Creds)
- Lateral Movement Tooling Spawned by FortiClient Process (locked: unlock with TL Creds)
- Vulnerable FortiClient Exposure Indicator: [indicator] Running (CVE-2026-121529) (locked: unlock with TL Creds)
- FortiClient Parent Spawning Privilege or Persistence Commands (locked: unlock with TL Creds)
- FortiClient Parent Spawning Download Cradle or Encoded Command (Ingress Tool Transfer) (locked: unlock with TL Creds)
- FortiClient-Spawned Interpreter Running as SYSTEM or High Integrity (CVE-2026-121529 Privilege Escalation Impact) (locked: unlock with TL Creds)
- FortiClient Process Outbound Connection to Non-Fortinet Public Destination (Possible C2 After CVE-2026-121529) (locked: unlock with TL Creds)

Sign up free to unlock the detection rules: https://threadlinqs.com/?modal=signup

## Sources

- [Fortinet PSIRT FG-IR-26-194: Origin validation error in local API endpoint](https://fortiguard.fortinet.com/psirt/FG-IR-26-194)
- [NVD CVE-2026-121529](https://nvd.nist.gov/vuln/detail/CVE-2026-121529)
- [Fortinet2Shell Vulnerability Lets Hackers Execute Code on FortiClient Systems Through Malicious Websites (GBHackers)](https://gbhackers.com/fortinet2shell-vulnerability/)
- [CVSS v3.1 calculator for the advisory vector](https://nvd.nist.gov/vuln-metrics/cvss/v3-calculator?vector=AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H/E:P/RL:O/RC:C&version=3.1)
- [CWE-346: Origin Validation Error](https://cwe.mitre.org/data/definitions/346.html)
- [Related (different flaw): FortiClient EMS CVE-2026-35616 exploited to deploy EKZ malware (GBHackers)](https://gbhackers.com/forticlient-code-execution-flaw/)

## Full data

The other 8 detection rules (Splunk SPL / Microsoft KQL / Sigma) unlock with TL Creds; a free account includes daily creds: https://threadlinqs.com/?modal=signup
Indicator values unlock with TL Creds, at a lower price on Red and Purple; AI agents can query rules and IOCs through the Threadlinqs MCP server (Purple): https://intel.threadlinqs.com/mcp

Canonical: https://intel.threadlinqs.com/threat/TL-2026-5802
