Neutron, our AI engine, scored 97.1% on UC Berkeley's CyberGym benchmark. Learn more

Deep Dive

Deep Dive

Apache OFBiz Pre-Auth RCE Fixed in 24.09.08 (CVE-2026-68524)

Apache OFBiz before 24.09.08 loads a screen definition from an attacker-chosen file descriptor on the login page and runs code; 46 CVEs are fixed.

TL;DR

  • Apache OFBiz loads a screen definition from a location an unauthenticated JSON request can set. An attacker points the login page at their own XML and runs code in the server process.
  • Every release before 24.09.08 is affected. The project published the fix in 24.09.08 and announced 46 CVEs in the same release on November 4, 2026.
  • Apache describes the batch as including critical issues and names seven code-execution flaws, several of them unauthenticated. CVE-2026-68524 is not in CISA KEV as of November 5, 2026, and no exploitation is known.
  • Upgrade every OFBiz instance to 24.09.08. The project publishes no workaround for the batch; see "How do I fix it?" for exposure reduction while you schedule the upgrade.

Am I affected?

All of these conditions must hold for an instance to be exposed:

  • The instance runs an OFBiz release before 24.09.08.
  • Its web application is reachable by the attacker. The login page and the webapp endpoints are enough; no account is needed.
  • The instance has not been patched with the 24.09.08 release. Custom components that embed OFBiz framework code need the same fix.

The project states that all versions before 24.09.08 are affected. That includes the 18.12 line and older releases that are no longer maintained.

Branch Affected versions Fixed version
24.09 24.09.01 to 24.09.07 24.09.08
18.12 18.12.19 and earlier 24.09.08
17.12 and older every release 24.09.08

Check the installed release:

basename "$(readlink -f "$OFBIZ_HOME")"
git -C "$OFBIZ_HOME" describe --tags 2>/dev/null

A binary install prints a directory such as apache-ofbiz-24.09.08. A source install prints a tag such as release24.09.08. For a container, run the same command inside it:

docker exec <container> sh -c 'basename "$(readlink -f "$OFBIZ_HOME")"'

The VERSION file at the root of the source tree says 24.09 for every point release in the series, so it cannot tell 24.09.07 from 24.09.08. Use the directory name, the git tag or the downloaded archive name.

How do I fix it?

  1. Back up the database and the runtime/ directory, which holds the instance configuration and secrets.
  2. Stop the OFBiz process. If it runs under Gradle, stop the ./gradlew ofbiz process or the service that wraps it.
  3. Download apache-ofbiz-24.09.08 from the project's download page and unpack it.
  4. Deploy it as you deploy any point release, keeping your runtime/ configuration and custom components. Do not run loadAll against an existing database: the project's README warns that the task can overwrite data.
  5. Start the new tree with ./gradlew ofbiz and check that the login page renders.
  6. Confirm the version with the check command from "Am I affected?" and repeat for every instance and container image.

No workaround is published for the batch. Until the upgrade is scheduled, reduce exposure:

  1. Put the OFBiz web interface behind a network allowlist so only known administrators can reach it.
  2. Do not expose the login page or the webapp endpoints directly to the internet.
  3. If a reverse proxy fronts OFBiz, reject JSON request bodies that carry a mainDecoratorLocation key or any attribute name that matches your decorator configuration.

Those steps reduce who can reach the vulnerable path. They do not fix the request-attribute merge or the widget location resolution.

What is the root cause?

OFBiz renders pages from XML screen definitions. A screen can include another screen with a location attribute, and a decorator's location is commonly a Flexible String Expression such as ${parameters.mainDecoratorLocation}. The value comes from the request context, so the widget factories treat it as attacker-controlled.

The first half of the flaw is in WebAppUtil.setAttributesFromRequestBody. It merged every key of an anonymous JSON request body into the request attributes:

if (requestBodyMap != null) {
    Set<String> parameterNames = requestBodyMap.keySet();
    for (String parameterName: parameterNames) {
        request.setAttribute(parameterName, requestBodyMap.get(parameterName));
    }
}

A request body could therefore set mainDecoratorLocation, even though the webapp already exposes that name as a trusted ServletContext attribute set from web.xml. The comment on the fix describes the consequence: the body could "shadow a webapp's configured decorator location".

The second half is the widget location resolver. ScreenFactory, FormFactory, GridFactory, MenuFactory and TreeFactory passed the location to FlexibleLocation.resolveLocation and parsed whatever XML came back.

The login page is rendered before authentication, and it uses the decorator location. A request that changes that location therefore reaches the widget parser without a session. The parser accepts any URL that FlexibleLocation can resolve, including the file: scheme. The fix adds one gatekeeper, WidgetSecureLocation, and its class comment names the carrier used in the reported chain:

/**
 * Any {@code file:} scheme location - single-slash or otherwise, in any letter case - is rejected
 * outright at the protocol layer: it is never a legitimate widget location, and on Linux it is the
 * carrier used to reach live process-descriptor aliases such as {@code file:/dev/fd/N} or
 * {@code file:/proc/thread-self/fd/N}.
 */
public static String sanitize(String location) {
    if (UtilValidate.isEmpty(location)) {
        return null;
    }
    if (isFileScheme(location) || UtilValidate.isUrlInStringAndDoesNotStartByComponentProtocol(location)) {
        return null;
    }
    if (location.startsWith(COMPONENT_PROTOCOL)) {
        String componentRelativePath = location.substring(COMPONENT_PROTOCOL.length());
        if (componentRelativePath.contains("..")) {
            return null;
        }
        // ...
        return COMPONENT_PROTOCOL + normalizedPath;
    }
    if (UtilValidate.isAllowedPath(location)) {
        return location;
    }
    return null;
}

The tests added with the fix use file:/dev/fd/292, file:/proc/self/fd/292, file:/proc/thread-self/fd/292 and file:/proc/%73elf/fd/292. A file descriptor stays open while the request is handled, so a request-controlled location can name its own body or an uploaded temporary file. The screen parser then reads attacker XML from that descriptor.

How is it exploited?

  1. The attacker sends an anonymous JSON request to the OFBiz login page or another pre-authentication endpoint.
  2. The JSON body sets mainDecoratorLocation to a file: location that names a descriptor the attacker can influence, for example file:/proc/self/fd/<n>.
  3. WebAppUtil copies the key into the request attributes, shadowing the trusted decorator location.
  4. The login page resolves the decorator through the widget factory, which reads the XML from the descriptor instead of a component:// path.
  5. The attacker's screen definition carries an action or a widget expression that the renderer executes.
  6. The code runs in the OFBiz Java process, as the operating-system user that runs OFBiz, before the user authenticates.

The second pre-authentication code-execution flaw in the batch, CVE-2026-83542, is described as login-page widget injection and is fixed with the same screen-location gate. CVE-2026-73578 is an unauthenticated saved-view authorization bypass with RCE impact. No public exploit code has been published for any of the three.

How does the attack flow?

The login page reads its decorator location from request context, and the fix closes both the attribute shadowing and the file-descriptor path.

flowchart LR A["Anonymous JSON body
sets mainDecoratorLocation"] --> B["Request body shadows
trusted ServletContext value"] B --> C["Login page resolves
the decorator location"] C --> D["file:/proc/self/fd/N
names the request stream"] D --> E["Screen factory parses
attacker XML"] E --> F["Screen action executes
before authentication"] F --> G["Code runs in the OFBiz JVM
as the OFBiz user"]

What can an attacker do?

An unauthenticated attacker runs arbitrary code in the OFBiz Java process, with the privileges of the user that runs the server. That user can read the instance configuration, reach the database with the configured credentials, and modify the application.

The impact needs all of these conditions:

  • The OFBiz web application is reachable from the attacker's network.
  • The instance runs a release before 24.09.08.
  • The attacker can set a request attribute through a JSON body and can name a file descriptor that holds their XML. The fix's tests show the descriptor paths the chain used.
  • The screen definition the attacker supplies contains an executable action.

The batch also carries other impacts that do not need the file-descriptor path. CVE-2026-105330 is a hard-coded cryptographic key in JWT authentication that enables unauthenticated administrative access. CVE-2026-109928 is an incorrect password-reset algorithm that enables full account takeover. Fifteen of the 46 CVEs are missing-authorization or authorization-bypass flaws, including cross-tenant and view-only cases.

Why does the fix work?

The fix puts every widget location through WidgetSecureLocation.sanitize before it is resolved. The function rejects any file: scheme regardless of case. It rejects .. inside a component:// path. It denies every other filesystem path unless an administrator has configured the new security.allowFilePaths regular expression. The property is empty by default, which makes non-component locations deny by default.

The fix also stops the shadowing at the source. WebAppUtil now skips a body key when the ServletContext already exposes an attribute with that name:

ServletContext servletContext = request.getServletContext();
Set<String> parameterNames = requestBodyMap.keySet();
for (String parameterName: parameterNames) {
    // A request body is anonymous, attacker-controlled input. Never let it shadow a name
    // the webapp already exposes as a trusted, application-owned ServletContext attribute
    if (servletContext.getAttribute(parameterName) != null) {
        Debug.logWarning("Ignoring request body attribute [%s]: it shadows an existing"
                + " ServletContext attribute of the same name", MODULE, parameterName);
        continue;
    }
    request.setAttribute(parameterName, requestBodyMap.get(parameterName));
}

Together, the two changes remove both halves of the chain. The attacker can no longer replace the decorator location, and a location that names a descriptor is no longer accepted.

The commit applies the check to screens, forms, grids, menus and trees. It adds unit tests for the allowlist and the file-scheme cases. It is complete for those five factories. Any custom widget factory outside the framework would need the same call.

How do I check if I was compromised?

No indicators of compromise are published for CVE-2026-68524 or the rest of the batch. A successful request can look like an ordinary login-page request, and the pre-fix code logged nothing when a body attribute shadowed a ServletContext attribute.

Two checks are worth running on an instance that was internet-facing:

  1. Search the web-server access log for JSON POST requests to the login or control endpoints, then inspect the bodies your proxy recorded for mainDecoratorLocation, decorator, location or screen keys. A body that sets a decorator location is a lead. A proxy that does not log bodies cannot answer this question.
  2. Search the OFBiz log for XML parse errors or widget warnings around the same requests. A malformed attacker screen produces a parser exception. A valid one may leave no entry.

Treat an unexplained pre-authentication request that names a decorator or a file: location as a possible compromise. Rebuild the instance from the 24.09.08 tree, rotate the database and mail credentials it holds, and review the accounts and scheduled jobs.

Timeline

  • 2026-07-30: the screen-location hardening is backported to the 24.09 branch in PR #1528.
  • 2026-08-14: the WidgetSecureLocation gate and the request-body shadowing fix merge in PR #1650 (commit 4afb9c9a), and PR #1654 backports them to the 24.09 branch.
  • 2026-10-21: the 24.09.08 release is tagged.
  • 2026-11-04: the project announces 46 CVEs in 24.09.08 on the oss-security mailing list.

The fix merged in July and August, the release was tagged in October, and the CVE batch was announced on November 4
Figure 1: From the first fix commit to the CVE announcement. Source: Apache OFBiz pull requests, release tag and oss-security announcement, checked November 5, 2026

FAQ

Which release fixes it?

Apache OFBiz 24.09.08 fixes all 46 CVEs in the batch. The project states that every release before 24.09.08 is affected, and it publishes no backports to the 18.12 or older lines, so those installs must move to 24.09.08.

Do I have to fix all 46 CVEs at once?

Yes, because all 46 ship in one release, 24.09.08. They range from code execution and hard-coded credentials to missing authorization, SQL and XML injection, path traversal, server-side request forgery, cross-site scripting, data disclosure and denial of service. Several are reachable without authentication.

Is there a workaround if I cannot upgrade this week?

The project publishes none. Restricting the web interface to known administrator networks and rejecting request bodies that set decorator attributes reduces exposure, but it does not remove the vulnerable code. Treat the upgrade as the fix.

Was CVE-2026-68524 exploited in the wild?

No exploitation is known as of November 5, 2026, and the CVE is not in CISA KEV. Apache announced the batch on November 4, 2026, and the public material contains no proof of concept.

Why are the CVE records not in the public databases yet?

The project announced the CVE identifiers on November 4, 2026. At the time of writing, the MITRE CVE Services API returned no records for the identifiers we checked. The advisory list and the fix commits are the available public sources. The identifiers and fix mappings are on the project's security page.

References

  • Apache OFBiz, "Apache OFBiz Security" page, list of known vulnerabilities and fix pull requests (checked November 5, 2026). https://ofbiz.apache.org/security.html
  • Apache OFBiz, "Apache OFBiz: CVE Announcements", oss-security, November 4, 2026 (checked November 5, 2026). https://www.openwall.com/lists/oss-security/2026/11/04/9
  • Apache OFBiz, "Download" page, release 24.09.08 (checked November 5, 2026). https://ofbiz.apache.org/download.html
  • Apache OFBiz, pull request #1650, "Restrict widget resource locations to component:// or an explicit allowlist" (checked November 5, 2026). https://github.com/apache/ofbiz-framework/pull/1650
  • Apache OFBiz, commit 4afb9c9a, the WidgetSecureLocation and request-body fix (checked November 5, 2026). https://github.com/apache/ofbiz-framework/commit/4afb9c9ab4d9fe7777c00f45eb07c961bcbc357a
  • Apache OFBiz, pull request #1654, the 24.09 backport of the widget location fix (checked November 5, 2026). https://github.com/apache/ofbiz-framework/pull/1654
  • Apache OFBiz, pull request #1528, the screen-location hardening backport (checked November 5, 2026). https://github.com/apache/ofbiz-framework/pull/1528
  • Apache OFBiz, release tag release24.09.08 (checked November 5, 2026). https://github.com/apache/ofbiz-framework/releases/tag/release24.09.08