CVE-2025-23184

Denial of Service
Affects
Apache CXF (org.apache.cxf:cxf-core)
in
Apache CXF
No items found.
Versions
<3.5.10, >=3.6.0 <3.6.5, >=4.0.0 <4.0.6

Patch Available.

Exclamation circle icon
Patch Available

This Vulnerability has been fixed in the Never-Ending Support (NES) version offered by HeroDevs.

Overview

Apache CXF is an open-source services framework, maintained by the Apache Software Foundation, for building and consuming web services in Java. It implements the JAX-WS and JAX-RS APIs and supports SOAP, the WS-* standards, RESTful HTTP, and OAuth 2.0 over transports such as HTTP and JMS. Its modules are published as Maven artifacts under org.apache.cxf.

A Denial of Service (DoS) vulnerability (CVE-2025-23184) has been identified in the CachedOutputStream class of Apache CXF, which allows attackers to fill the file system of a CXF server or client with temporary files that are never deleted. In some edge cases, CachedOutputStream instances that have spilled their content to a temporary file are never closed, and nothing else ever removes those files.

Per OWASP: The Denial of Service (DoS) attack is focused on making a resource (site, application, server) unavailable for the purpose it was designed. There are many ways to make a service unavailable for legitimate users by manipulating network packets, programming, logical, or resources handling vulnerabilities, among others.

This issue affects all versions before 3.5.10, versions 3.6.0 through 3.6.4, and versions 4.0.0 through 4.0.5 of Apache CXF.

Details

Module Info

Vulnerability Info

This High-severity vulnerability (NVD CVSS v3.1 base score 7.5, CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H) is found in the org.apache.cxf:cxf-core package in all versions before 3.5.10, 3.6.0 through 3.6.4, and 4.0.0 through 4.0.5 of Apache CXF.

CXF buffers message content in CachedOutputStream, which is used on both the server and client side (for example, by the HTTP conduits, the logging interceptors, and attachment handling). Once a payload grows past the cache threshold (128 KiB by default), the stream spills its content to a temporary file:

private void createFileOutputStream() throws IOException {
    if (tempFileFailed) {
        return;
    }
    ByteArrayOutputStream bout = (ByteArrayOutputStream)currentStream;
    try {
        if (outputDir == null) {
            tempFile = FileUtils.createTempFile("cos", "tmp");
        } else {
            tempFile = FileUtils.createTempFile("cos", "tmp", outputDir, false);
        }

        currentStream = createOutputStream(tempFile);
        bout.writeTo(currentStream);
        inmem = false;
        streamList.add(currentStream);
    } catch (Exception ex) {
        ...
    }
}

The only code that removes that file runs when the owner calls close(), and even then the file is deleted only after every stream handed out by getInputStream() has also been closed:

public void close() throws IOException {
    currentStream.flush();
    outputLocked = true;
    if (null != callbacks) {
        for (CachedOutputStreamCallback cb : callbacks) {
            cb.onClose(this);
        }
    }
    doClose();
    currentStream.close();
    if (ciphers != null) {
        ciphers.clean();
    }
    if (!maybeDeleteTempFile(currentStream)) {
        postClose();
    }
}

private boolean maybeDeleteTempFile(Object stream) {
    boolean postClosedInvoked = false;
    streamList.remove(stream);
    if (!inmem && tempFile != null && streamList.isEmpty() && allowDeleteOfFile) {
        ...
        deleteTempFile();
        currentStream = new LoadingByteArrayOutputStream(1024);
        inmem = true;
    }
    return postClosedInvoked;
}

Nothing tracks file-backed instances outside this lifecycle. No Bus-level registry exists, no timed cleanup runs, and nothing happens at Bus shutdown. If a processing path fails, for example because an exception interrupts the interceptor chain or a close callback throws, close() is skipped or cut short. The same happens when a consumer abandons an input stream obtained from getInputStream() without closing it. In each case the cos*.tmp file stays on disk for the life of the JVM. An attacker who can repeatedly send large messages that reach such a path makes the service leak one temporary file per request. The files pile up until the temporary directory's file system is full, and the service and anything else sharing that disk start to fail.

This vulnerability was introduced in 2006 with Apache CXF 2.0-incubator-M1.

Mitigation

The 3.4.x line was already End-of-Life when this CVE was published and will not receive public updates to address this issue.

Users of the affected components should apply one of the following mitigations:

  • Upgrade to a currently supported Apache CXF release line (3.6.x or later) that contains the fix.
  • Leverage a commercial support partner like HeroDevs for post-EOL security support.
Vulnerability Details
Severity
Level
CVSS Assessment
Low
>=0 <4
Medium
>=4 <6
High
>=6 <8
Critical
>=8 <10
High
ID
CVE-2025-23184
PROJECT Affected
Apache CXF (org.apache.cxf:cxf-core)
Versions Affected
<3.5.10, >=3.6.0 <3.6.5, >=4.0.0 <4.0.6
NES Versions Affected
Published date
October 1, 2026
≈ Fix date
September 30, 2026
Category
Denial of Service
Vex Document
Download VEXHow do I use it?
Sign up for the latest vulnerability alerts fixed in
NES for Apache CXF
Rss feed icon
Subscribe via RSS
or

By submitting the form I acknowledge receipt of our Privacy Policy.

Thanks for signing up for our Newsletter! We look forward to connecting with you.
Oops! Something went wrong while submitting the form.