flawopen.com/Teardowns/cve-2026-104286-fortimail-ibe-path-traversal
CVE-2026-104286: FortiMail IBE Path Traversal
CVE-2026-104286 lets unauthenticated HTTP(S) requests write files on vulnerable FortiMail systems through path traversal. Fortinet reports in-the-wild exploitation; disable IBE or restrict web access, investigate for compromise, and install the correct fixed release.[1], [5]
A mail gateway is like a locked mailroom with a clerk who files attachments. The flaw lets a request give the clerk a misleading folder path, so a file can be written outside the intended drop-off area. Fortinet's workaround closes the affected IBE door or limits who can reach the web interface while administrators patch and check whether anyone already got in.[1], [5]
Core Concepts & Subsystem Terms
Path traversal (CWE-22)- Untrusted path components escape the directory intended for a file operation. Fortinet describes unauthenticated arbitrary file writes on affected FortiMail systems.[1], [6]
Identity-Based Encryption (IBE)- FortiMail functionality for encrypted-message workflows. Fortinet's temporary workaround is to disable IBE; account for the effect on users who rely on it.[1], [5]
Framework mappings
- CWE reference for the weakness described in this guide: CWE-22
- CISA KEV — added 2026-10-01 — CVE-2026-104286
Root Cause Analysis
Fortinet describes CVE-2026-104286 as an unauthenticated path-traversal flaw that can write arbitrary files through HTTP or HTTPS requests. The vendor's firmware is closed source, and the public advisory does not provide vulnerable source lines or a source patch diff; this article does not invent them. Public government advisories confirm the arbitrary-file-write impact, exploitation, and version guidance, but do not describe FortiMail's internal handler. Fortinet's advisory is the source for the IBE-disable or web-access-restriction workaround and the published IOCs. Contain and investigate the appliance, then apply the product-appropriate fixed release; a clean IOC check alone is not proof of safety. The CVE record's prose description lists 7.2.0–7.2.9, 7.4.0–7.4.8, 7.6.0–7.6.6, and 8.0.0–8.0.1. Its structured version table gives shorter upper bounds for 7.4 and 7.6 and additionally lists 7.0.0–7.0.9, unlike the public government summaries. The same record's solutions section lists upcoming 7.4.8, 7.6.6, 8.0.1, and 7.2.10, conflicting with both its affected-range data and the October 1 Canadian advisory. Use that dated government advisory as the published operational guidance, and confirm current release availability and the 7.0 scope with Fortinet; do not infer a fixed build from the conflicting CNA fields.[1], [3], [5], [4], [6], [7]
Operator matrix: branch scope and first response
| Area | What authoritative sources say | Defender action |
|---|---|---|
| FortiMail 7.0 | NVD/CNA data lists 7.0.0–7.0.9; the Canadian and French government summaries do not list branch 7.0. The same record’s prose and structured table also disagree on the 7.4 and 7.6 upper bounds. The record’s solutions section also lists upcoming but lower builds (7.4.8, 7.6.6, 8.0.1, and 7.2.10), which conflict with its affected ranges and the Canadian advisory. | Ask Fortinet to confirm the branch status; do not infer that an omitted branch is safe. |
| FortiMail 7.2 | The Canadian advisory says to upgrade to branch 7.4 or later. | Plan migration to a fixed supported branch; do not assume a 7.2 patch exists. |
| FortiMail 7.4 / 7.6 / 8.0 | The Canadian advisory lists fixes at 7.4.9, 7.6.7, and 8.0.2, respectively. | Use Canada advisory AV26-989 as the published build guidance; verify availability and support in Fortinet’s current bulletin before upgrading. Do not rely on the lower CNA solution cutoffs. |
| Containment and investigation | Fortinet reports exploitation and publishes IOCs; its workaround is to disable IBE or restrict web access. | Preserve evidence, apply the workaround, review the vendor IOCs, then patch and assess compromise. |
Step-by-Step Attack Flow
Source Code: Flaw vs. Secure Implementation
FortiMail firmware source and the vendor patch diff are not public, so this is a generic Python defense pattern, not Fortinet code or a reproduction. It opens a trusted directory once, uses a server-generated opaque filename, and creates a new regular file relative to that directory descriptor with exclusive creation and no-follow flags. It is POSIX-specific and fails closed when required flags are unavailable. For nested paths, walk one validated component at a time using directory descriptors; never check a string path and later reopen it by name. Apply Fortinet’s supported product update or workaround to remediate CVE-2026-104286. All components of the configured root path, including its parent directories, must remain administrator-controlled; O_NOFOLLOW protects only the final component when opening that root.
Source excerpt: Generic illustrative path-boundary example; not FortiMail source
from pathlib import Path
def destination(root: Path, request_path: str) -> Path:
# Illustrates the unsafe design: caller input is joined
# to a trusted directory without a containment check.
return root / request_path
import os
import uuid
# Open the trusted, service-owned directory once; its path ancestors must stay administrator-controlled.
def open_upload_root(root):
required = ("O_DIRECTORY", "O_NOFOLLOW")
if not all(hasattr(os, flag) for flag in required) or os.open not in os.supports_dir_fd:
raise RuntimeError("POSIX directory protections unavailable")
flags = os.O_RDONLY | os.O_DIRECTORY | os.O_NOFOLLOW
return os.open(root, flags)
# Do not turn a request path into a filesystem path; generate an opaque name.
# O_EXCL fails if a name exists; O_NOFOLLOW rejects a final symlink.
ROOT_FD = open_upload_root("/srv/app-private/uploads")
def create_upload_file():
name = uuid.uuid4().hex
flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_NOFOLLOW
fd = os.open(name, flags, 0o600, dir_fd=ROOT_FD)
return name, fd
Engineering & System Hardening Checklist
- ✓Inventory all FortiMail appliances and branch/builds. Use Fortinet's current advisory as the authority; because CNA data also lists 7.0.0–7.0.9 while the vendor summary omits 7.0, ask Fortinet to confirm those installations.[1], [5], [6]
- ✓Apply the current vendor workaround immediately: disable IBE, or remove public access to the relevant web interface and restrict it to trusted private networks. Test the business impact of disabling IBE with mail owners.[1]
- ✓Preserve appliance logs, configuration backups, and relevant forensic evidence before rebooting or upgrading. Check the current IOC list in Fortinet advisory FG-IR-26-175 and investigate matches as a potential incident.[1], [4]
- ✓Use Canada advisory AV26-989 as the published build guidance; verify availability and support in Fortinet’s current bulletin before upgrading. Do not rely on the lower CNA solution cutoffs.[5], [1], [7]
- ✓Treat patching and compromise assessment as separate tasks. A fixed build does not remove files, credentials, or persistence placed before remediation; use incident-response procedures if indicators or suspicious behavior are found.
- ✓For custom file handlers, validate the canonical resolved path against an allowlisted root after one strict decode, reject NUL and malformed encodings, and open files relative to a trusted directory handle to prevent symlink races.
Sources
- Fortinet PSIRT — FG-IR-26-175 / CVE-2026-104286
- CISA Known Exploited Vulnerabilities — CVE-2026-104286
- Cyber Security Agency of Singapore — active exploitation advisory
- CERT-FR — Fortinet FortiMail vulnerability
- Government of Canada Cyber Centre — Fortinet advisory AV26-989
- NVD — CVE-2026-104286 record and version data
- CVE Program record — Fortinet CNA data