Endpoint management servers are a blind spot precisely because they are defensive tools. FortiClient EMS exists to push policy and posture to the endpoint agents across a fleet, so it is trusted, often internet-adjacent for remote-agent check-in, and quietly exempted from the input-validation scrutiny a public web app would get. That is the wrong instinct. A server that manages endpoints is a server that, once compromised, speaks with authority to every endpoint it manages. The class here is old and the fix is well understood; what makes this instance matter is where it lands. Verifiable security.
The mechanism: untrusted string reaches SQL text
Strip the product name away and the bug is a single sentence: attacker-controlled input reaches SQL query text without parameterization. A pre-authentication HTTP request carries a field the server was supposed to treat as data. Instead of binding that field as a parameter, the handler concatenates it directly into the statement it hands the database. The moment the value crosses into query text, the attacker is no longer supplying data; they are supplying syntax. They can close the intended clause, append their own, and have the database execute it.
On many targets that is where the story pauses, at reading or altering rows. FortiClient EMS is not one of those targets. The database service on the EMS host runs with high privilege, and high-privilege database engines expose primitives that reach outside the data tier: stacked queries that run multiple statements in one request, and the ability to write attacker-chosen bytes to a location on disk the operating system will later execute or load. Chain those and the injection stops being a data problem. The database becomes the attacker's hands on the host, and the result is command execution with the privilege of the service. No credentials were presented at any point, because the vulnerable path answers before authentication.
This is not a novel weakness so much as a repeat with a familiar surname. FortiClient EMS carried an earlier SQL injection of the same lineage in CVE-2023-48788, and the fix boundary is identical: parameterize the query so the untrusted value can never be read as SQL syntax. When the same class returns to the same product two years later, the lesson is that any code path where a request field can reach a SQL statement is a candidate until every one binds its inputs.
Affected 7.4.0 through 7.4.4; fixed in 7.4.5. Illustrative, defender-level; no weaponized payload.
Why the endpoint manager is the wrong host to lose
Severity here is not a scanner reflex, it is arithmetic. Unauthenticated means no barrier of entry. SQL injection to command execution means full read, write, and run on the host. And the host is the one that manages your endpoint fleet, which makes it a pivot point rather than a leaf. An attacker who owns the EMS server owns the vantage point that endpoint agents are configured to trust: a bug at the center of the estate, not on its edge.
Where to be precise, because precision is the brand: not every EMS deployment is reachable from an untrusted segment, and only builds 7.4.0 through 7.4.4 are affected, with 7.4.5 carrying the fix. A patched instance, or one whose management surface is confined to a trusted network, carries a small fraction of the risk. The work is not to assume every EMS is exploitable. It is to determine, for your estate, which instances are on an affected build and reachable from somewhere you do not control.
A server that manages endpoints is a server that, once compromised, speaks with authority to every endpoint it manages.
Detection without weaponization
You do not need to run an exploit to know whether you are exposed, and you should not exfiltrate data to prove a point. Two readable facts settle most of it, and a single non-destructive differential settles the rest.
- Version fingerprint. Identify the EMS build. Anything in 7.4.0 through 7.4.4 is affected; 7.4.5 is fixed. Cross-reference the version against the KEV catalog entry dated 13 April 2026, which records observed exploitation, not theoretical risk.
- Network position. Flag any EMS instance reachable from an untrusted segment. The pre-auth surface is the part that answers strangers; that is where an injection bug lands.
- Behavioral differential. In a lab or with authorization, a boolean or time-based probe on the injectable parameter demonstrates the injection without reading a single row. A response that changes shape on a true-versus-false condition, or a response that stalls on a deliberate delay, is signal enough. This proves the bug exists without touching the data it protects.
For monitoring, the pre-auth endpoints of an endpoint manager are a small, well-defined surface, which makes anomalous request shapes against them a high-signal indicator. Malformed input aimed at a parameter that should only carry structured data is worth an alert, not a log line.
How Celvex catches this
Find. Prove. Fix. Verify.
A read-only sweep version-fingerprints every EMS instance, flags any reachable from an untrusted segment, and cross-references the build against the KEV entry for CVE-2026-21643, all without sending a malicious payload.
A boolean or time-based differential on the injectable parameter demonstrates injection without exfiltrating data, and the result becomes an Ed25519-signed Proof Capsule carrying the host, the version evidence, and the KEV entry.
The capsule names the remediation: upgrade to 7.4.5, which parameterizes the vulnerable query, and restrict the EMS management surface so it no longer answers from untrusted segments.
Re-run the same differential after patching. No timing or boolean signal, and response-shape invariance across true and false conditions, confirms the query is parameterized and the finding closes.
What we add is not a new CVE. The vulnerability is in the vendor's code, and the upgrade to 7.4.5 is the fix. What we produce is the exposure determination for you: which EMS instances are on an affected build, reachable from where, and therefore carry the catalog's risk right now, backed by a differential that proves the bug and a re-run that proves the patch held.
The endpoint manager gets skipped because it is filed under security tooling, as if the tools that defend the fleet are exempt from the boundary question. They are not. Any place a stranger's input can reach a SQL statement is a place to check, on your management servers most of all. Answer it there and this class stops being a blind spot.
Verifiable security. Find it. Prove it. Fix it. Verify the fix held. That is what we ship.
Sources
Which of your trust anchors take outside input before login?
Free Exposure Check, no signup required. We map your internet-facing management servers, fingerprint their versions against the known-exploited catalog, and ship a signed Proof Capsule for the highest-confidence finding.
Run a Free Scan →