VYPR
Moderate severityNVD Advisory· Published Jul 11, 2025· Updated Nov 4, 2025

Apache Commons Lang, Apache Commons Lang: ClassUtils.getClass(...) can throw a StackOverflowError on very long inputs

CVE-2025-48924

Description

Uncontrolled Recursion vulnerability in Apache Commons Lang.

This issue affects Apache Commons Lang: Starting with commons-lang:commons-lang 2.0 to 2.6, and, from org.apache.commons:commons-lang3 3.0 before 3.18.0.

The methods ClassUtils.getClass(...) can throw StackOverflowError on very long inputs. Because an Error is usually not handled by applications and libraries, a StackOverflowError could cause an application to stop.

Users are recommended to upgrade to version 3.18.0, which fixes the issue.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Uncontrolled recursion in Apache Commons Lang's ClassUtils.getClass() can cause StackOverflowError on long inputs, leading to denial of service.

Vulnerability

CVE-2025-48924 is an uncontrolled recursion vulnerability in Apache Commons Lang's ClassUtils.getClass() methods. The issue affects commons-lang:commons-lang from version 2.0 to 2.6, and org.apache.commons:commons-lang3 from 3.0 before 3.18.0 [1][4]. The methods use recursion to process class names, and when provided with extremely long inputs, the recursion depth exceeds the Java stack limit, throwing a StackOverflowError [2].

Exploitation

An attacker can trigger the vulnerability by supplying a crafted, very long class name string to ClassUtils.getClass(). No authentication is required if the application accepts untrusted input that is passed to this method. The attack vector is simple: any mechanism that allows an attacker to control the class name argument can lead to the error [1][4].

Impact

Since StackOverflowError is an Error subclass, it is not typically caught by application or library error handling, causing the application to terminate. This results in a denial of service (DoS) condition. The vulnerability has a low CVSS severity due to the requirement of long input and the availability of a fix [1][4].

Mitigation

The fix was implemented in Apache Commons Lang 3.18.0 by rewriting the getClass() methods to avoid recursion [2]. Users are strongly recommended to upgrade to version 3.18.0 or later. For versions prior to 3.0 (i.e., the old commons-lang group), no patch is available as it is end-of-life; migration to commons-lang3 is advised [1][4].

AI Insight generated on May 19, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
org.apache.commons:commons-lang3Maven
>= 3.0, < 3.18.03.18.0
commons-lang:commons-langMaven
>= 2.0, <= 2.6

Affected products

2
  • Range: 2.0 - 2.6
  • Apache Software Foundation/Apache Commons Langv5
    Range: 3.0

Patches

1
b424803abdb2

Rewrite ClassUtils.getClass() without recursion to avoid

https://github.com/apache/commons-langGary GregorySep 21, 2024via ghsa
3 files changed · +18 19
  • src/changes/changes.xml+2 1 modified
    @@ -50,7 +50,8 @@ The <action> type attribute can be add,update,fix,remove.
         <action                   type="fix" dev="ggregory" due-to="Gary Gregory">Fix flaky FileUtilsWaitForTest.testWaitForNegativeDuration().</action>
         <action                   type="fix" dev="ggregory" due-to="Gary Gregory">Pick up exec-maven-plugin version from parent POM.</action>
         <action                   type="fix" dev="ggregory" due-to="Gary Gregory">Speed up and sanitize StopWatchTest.</action>
    -    <action                   type="fix" dev="ggregory" due-to="Fabrice Benhamouda">Fix handling of non-ASCII letters and numbers in RandomStringUtils #1273.</action> 
    +    <action                   type="fix" dev="ggregory" due-to="Fabrice Benhamouda">Fix handling of non-ASCII letters and numbers in RandomStringUtils #1273.</action>
    +    <action                   type="fix" dev="ggregory" due-to="OSS-Fuzz, Gary Gregory">Rewrite ClassUtils.getClass(...) without recursion to avoid StackOverflowError on very long inputs. OSS-Fuzz Issue 42522972: apache-commons-text:StringSubstitutorInterpolatorFuzzer: Security exception in org.apache.commons.lang3.ClassUtils.getClass.</action>
         <!-- ADD -->
         <action                   type="add" dev="ggregory" due-to="Gary Gregory">Add Strings and refactor StringUtils.</action>
         <!-- UPDATE -->
    
  • src/main/java/org/apache/commons/lang3/ClassUtils.java+16 18 modified
    @@ -527,24 +527,21 @@ public static Class<?> getClass(final ClassLoader classLoader, final String clas
          * @throws ClassNotFoundException if the class is not found
          */
         public static Class<?> getClass(final ClassLoader classLoader, final String className, final boolean initialize) throws ClassNotFoundException {
    -        try {
    -            final Class<?> clazz = getPrimitiveClass(className);
    -            return clazz != null ? clazz : Class.forName(toCanonicalName(className), initialize, classLoader);
    -        } catch (final ClassNotFoundException ex) {
    -            // allow path separators (.) as inner class name separators
    -            final int lastDotIndex = className.lastIndexOf(PACKAGE_SEPARATOR_CHAR);
    -
    -            if (lastDotIndex != -1) {
    -                try {
    -                    return getClass(classLoader, className.substring(0, lastDotIndex) + INNER_CLASS_SEPARATOR_CHAR + className.substring(lastDotIndex + 1),
    -                        initialize);
    -                } catch (final ClassNotFoundException ignored) {
    -                    // ignore exception
    +        // This method was re-written to avoid recursion and stack overflows found by fuzz testing.
    +        String next = className;
    +        int lastDotIndex = -1;
    +        do {
    +            try {
    +                final Class<?> clazz = getPrimitiveClass(next);
    +                return clazz != null ? clazz : Class.forName(toCanonicalName(next), initialize, classLoader);
    +            } catch (final ClassNotFoundException ex) {
    +                lastDotIndex = next.lastIndexOf(PACKAGE_SEPARATOR_CHAR);
    +                if (lastDotIndex != -1) {
    +                    next = next.substring(0, lastDotIndex) + INNER_CLASS_SEPARATOR_CHAR + next.substring(lastDotIndex + 1);
                     }
                 }
    -
    -            throw ex;
    -        }
    +        } while (lastDotIndex != -1);
    +        throw new ClassNotFoundException(next);
         }
     
         /**
    @@ -1504,9 +1501,10 @@ public static Class<?> primitiveToWrapper(final Class<?> cls) {
         private static String toCanonicalName(final String className) {
             String canonicalName = StringUtils.deleteWhitespace(className);
             Objects.requireNonNull(canonicalName, "className");
    -        if (canonicalName.endsWith("[]")) {
    +        final String arrayMarker = "[]";
    +        if (canonicalName.endsWith(arrayMarker)) {
                 final StringBuilder classNameBuffer = new StringBuilder();
    -            while (canonicalName.endsWith("[]")) {
    +            while (canonicalName.endsWith(arrayMarker)) {
                     canonicalName = canonicalName.substring(0, canonicalName.length() - 2);
                     classNameBuffer.append("[");
                 }
    
  • src/test/java/org/apache/commons/lang3/ClassUtilsOssFuzzTest.java+0 0 added

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

9

News mentions

0

No linked articles in our index yet.