Fortinet has shipped an emergency fix for CVE-2026-35616, a critical flaw in FortiClient Endpoint Management Server (EMS) that attackers have been abusing in the wild since at least March 31, 2026. Rated CVSS 9.1, the bug lets a remote, unauthenticated attacker bypass certificate-based authentication by spoofing HTTP headers, handing them authenticated access to the EMS API. FortiClient EMS 7.4.5 and 7.4.6 are affected, and Fortinet has confirmed active exploitation — making this a drop-everything patch for any organization running those builds.

What CVE-2026-35616 actually is

Early coverage described the issue loosely as a "privilege escalation" flaw. The more precise picture, documented by Bishop Fox, is a pre-authentication API bypass: a remote attacker with no credentials can defeat FortiClient EMS's certificate-based client authentication and reach the API as a trusted device.

The root cause is a trust mismatch between the web tier and the application tier. EMS runs a Django application behind Apache. When Apache terminates mutual TLS with mod_ssl, it normally passes the client-certificate verification result to Django through WSGI environment variables. The Django code, however, also trusts the corresponding user-controllable HTTP request headersX-SSL-CLIENT-VERIFY and X-SSL-CLIENT-CERT — as if they were equivalent to those server-set values. Critically, the Apache configuration never strips those headers from inbound requests, so anything a client sends in them flows straight through to the application.

Compounding the problem, the certificate-chain validation only performs Distinguished Name string matching — it does no cryptographic signature verification. That means an attacker can forge a certificate with the right DN strings and pass validation outright.

  • CVE ID: CVE-2026-35616
  • CVSS score: 9.1 (Critical)
  • Affected versions: FortiClient EMS 7.4.5 and 7.4.6
  • Impact: Pre-authentication bypass of certificate-based auth, leading to authenticated API access and full system compromise
  • Exploitation: Confirmed in the wild since March 31, 2026

Because EMS is the central management plane for endpoint policy across an organization, authenticated API access can cascade across the entire managed device fleet.

How the bypass works

The attack chains the two weaknesses together:

  1. The attacker sends a request to an EMS API endpoint with the spoofed header X-SSL-CLIENT-VERIFY: SUCCESS, plus a forged certificate in X-SSL-CLIENT-CERT.
  2. Apache leaves those headers intact and forwards them to Django.
  3. Django treats X-SSL-CLIENT-VERIFY: SUCCESS as proof that mod_ssl validated the client certificate.
  4. The chain check (validate_cert_chain()) only compares Distinguished Name strings, so a forged certificate with matching DNs passes without any signature verification.
  5. The attacker is now treated as an authenticated, trusted device.

Proof of concept and detection

Bishop Fox published a non-destructive checkerCVE-2026-35616-check — that determines whether a server is vulnerable without authenticating or disrupting the service. The methodology is a clean differential test against the device-auth init endpoint:


POST /api/v1/fabric_device_auth/fortigate/init

The tool issues two requests and compares the responses:

  1. A baseline POST with no spoofed headers.
  2. The same POST with X-SSL-CLIENT-VERIFY: SUCCESS but no certificate PEM data.

Sending the verify header without any certificate data is enough to reach the vulnerable code path but cannot actually authenticate, because no certificate chain is supplied — so the server stays stable and keeps serving connections. The outcomes:

  • Vulnerable servers return different responses for the two requests. The baseline returns HTTP 401 (Certificate not found in request header), while the spoofed request returns HTTP 500. The header passes the contains_certificate() gate, but validate_cert_chain() then crashes on the missing PEM data, producing the server error.
  • Patched servers return identical HTTP 401 responses for both requests, because the hotfix adds Apache RequestHeader unset directives that strip the spoofable headers before they ever reach Django.

That 401-vs-500 divergence is a reliable, safe vulnerability signal you can use across a fleet.

Mitigation and remediation

Treat any EMS 7.4.5 or 7.4.6 deployment as potentially compromised until it is patched and reviewed. Recommended actions:

  • Patch immediately. Upgrade FortiClient EMS to the latest release that addresses CVE-2026-35616, per Fortinet's official security advisory. (The fix works by adding Apache RequestHeader unset directives that strip the spoofable X-SSL-CLIENT-* headers.)
  • Audit access and event logs for anomalous device-auth or API activity, with particular attention to the window from March 31, 2026 to now.
  • Reduce exposure. Do not expose the EMS management interface directly to the internet; restrict it with network segmentation and strict firewall rules.
  • Enforce MFA on all administrative accounts tied to EMS.
  • Apply least privilege to EMS service accounts and admin roles to shrink the blast radius of any successful access.
  • Hunt for IOCs associated with this CVE in coordination with your threat-intelligence provider.

Managed service and security providers running a shared EMS instance across multiple clients face compounded risk — a single exploitation event could affect several downstream organizations at once.

The bigger picture

This is another reminder that remote-access and endpoint-management infrastructure sits at the intersection of deep trust and external exposure, which makes it prime territory for initial-access brokers and ransomware operators. The Zscaler ThreatLabz 2026 VPN Risk Report (with Cybersecurity Insiders) makes the same point at scale: AI-assisted attack tooling has compressed the window between initial access and full compromise, and perimeter VPN architectures correlate with higher breach rates than zero-trust network access (ZTNA) models. A flaw in a component as trusted as EMS is exactly the scenario ZTNA's continuous verification, least-privilege micro-segmentation, and device-posture checks are meant to contain.

References