Skip to content

sassoftware/commons-lang

Repository files navigation

CVE-2025-48924 Remediation

This branch contains the remediation of the security vulnerability reported in CVE-2025-48924, an Uncontrolled Recursion vulnerability in Apache Commons Lang.

Vulnerability Overview

  • CVE ID: CVE-2025-48924
  • Type: Uncontrolled Recursion (CWE-674)
  • Severity: High
  • Published: July 11, 2025
  • CVSS Score: 7.5

Affected Versions

  • commons-lang:commons-lang 2.0 through 2.6
  • org.apache.commons:commons-lang3 3.0 through 3.17.x

Fixed Versions

  • org.apache.commons:commons-lang3 3.18.0 (official Apache fix)
  • This branch: commons-lang 2.6 with this fix

Vulnerability Description

The ClassUtils.getClass() method in Apache Commons Lang contains an uncontrolled recursion vulnerability. When processing class names with excessive nesting levels (e.g., "a.b.c.d.e..."), the method recursively attempts to resolve the class name by replacing package separators (.) with inner class separators ($). With deeply nested class names (thousands of levels), this causes unbounded recursion leading to a StackOverflowError.

Security Impact

An attacker who can control input to ClassUtils.getClass() could potentially crash the application by providing a maliciously crafted class name with thousands of nested package levels. This vulnerability manifests in two ways:

  1. StackOverflowError (Primary Threat): The most common manifestation where recursive calls exhaust the thread stack, typically occurring with default stack sizes (1MB) and moderate nesting (~4000 levels). Since StackOverflowError is an Error and typically unhandled by applications, this results in immediate application termination.

  2. OutOfMemoryError (Secondary Threat): With larger stack sizes (>2MB) or extremely deep nesting (>8000 levels), the deep recursion can cause heap exhaustion through intermediate string operations during recursive calls. Like StackOverflowError, this is typically unhandled and causes application failure.

Both manifestations result in a Denial of Service (DoS) condition, as Error types are generally not caught or handled by application code or libraries.

Remediation Details

Implementation Approach

This fix adopts the iterative approach, completely eliminating recursion from the ClassUtils.getClass() method.

Original Vulnerable Code (Recursive):

private static Class getClass(ClassLoader classLoader, String className, 
                              boolean initialize, int depth) throws ClassNotFoundException {
    // ... attempt to load class
    // If ClassNotFoundException, recursively try replacing last '.' with '$'
    return getClass(classLoader, next, initialize, depth + 1);  // RECURSIVE CALL
}

Fixed Code (Iterative):

public static Class getClass(ClassLoader classLoader, String className, 
                            boolean initialize) throws ClassNotFoundException {
    String next = className;
    int lastDotIndex = -1;
    do {
        try {
            // Attempt to load class with current name
            return clazz;
        } catch (ClassNotFoundException ex) {
            // Replace last '.' with '$' and try again
            lastDotIndex = next.lastIndexOf(PACKAGE_SEPARATOR_CHAR);
            if (lastDotIndex != -1) {
                next = next.substring(0, lastDotIndex) + 
                       INNER_CLASS_SEPARATOR_CHAR + next.substring(lastDotIndex + 1);
            }
        }
    } while (lastDotIndex != -1);
    throw new ClassNotFoundException(next);
}

Key Changes

  1. Eliminated Recursion: Replaced recursive implementation with iterative do-while loop
  2. No Depth Limiting: No maximum depth constant needed - stack overflow impossible
  3. Same Behavior: Maintains identical API and exception handling
  4. No Breaking Changes: Fully backward compatible

Modified Files

  • src/main/java/org/apache/commons/lang/ClassUtils.java

    • Lines 738-778: Replaced recursive getClass() with iterative implementation
    • Added comprehensive JavaDoc documenting CVE remediation
    • Author: Jinwoo Hwang (CVE-2025-48924 fix)
  • src/test/java/org/apache/commons/lang/CVE202548924Test.java (NEW)

    • Purpose: Comprehensive security test to detect and validate CVE-2025-48924 remediation
    • Lines: 221 lines with extensive JavaDoc documentation
    • Author: Jinwoo Hwang

    Key Features:

    • Dynamic Depth Calculation: Automatically calculates appropriate nesting depth based on JVM stack size

      • Parses -Xss and -XX:ThreadStackSize JVM arguments
      • Uses empirically determined ratio of 4 nesting levels per KB of stack
      • Defaults to 1024 KB (1 MB) if no explicit stack size configured
      • Caps at 8000 levels to prevent heap exhaustion from string construction
    • Multi-Threat Detection: Tests for both vulnerability manifestations:

      • StackOverflowError: Primary threat from recursive calls exhausting thread stack
      • OutOfMemoryError: Secondary threat from deep recursion with large stacks causing heap exhaustion
    • Test Methodology:

      • Constructs deeply nested class name (e.g., "very.long.very.long...ClassName")
      • Passes to ClassUtils.getClass() to trigger vulnerability
      • Expected behavior (post-fix): ClassNotFoundException (normal failure for non-existent class)
      • Vulnerability indicators (pre-fix): StackOverflowError or OutOfMemoryError
    • Stack Size Adaptability:

      • 512 KB stack → ~2048 nesting levels
      • 1 MB stack (default) → ~4096 nesting levels
      • 2 MB stack → ~8000 nesting levels (capped)
    • Test Results:

      • Pre-fix (vulnerable): FAILED in ~39.5 seconds with StackOverflowError
      • Post-fix (remediated): PASSED in ~41.5 seconds with ClassNotFoundException

Validation Results

Test Suite Results

Full Maven Test Suite:

  • Total Tests: 1,974
  • Failures: 0
  • Errors: 0
  • Skipped: 0
  • Time: 1 minute 11 seconds
  • Status: ✅ ALL PASSED

CVE-2025-48924 Specific Test:

  • Pre-fix (vulnerable): FAILED in 39.5s with StackOverflowError or OutOfMemoryError
  • Post-fix (remediated): PASSED in 41.5s with ClassNotFoundException

Comparative Validation

Original commons-lang 2.6 (Maven Central):

Test Result: FAILED in 24.5s
Error: StackOverflowError or OutOfMemoryError (vulnerability confirmed)

Fixed commons-lang 2.6-CVE-2025-48924.jar:

Test Result: PASSED in 26s
Status: OK (1 test)

Build Information

Building the Fixed JAR

mvn clean package -DskipTests

Output:

  • target/commons-lang-2.6-CVE-2025-48924.jar
  • Build Status: SUCCESS

Running Tests

Full Test Suite:

mvn test

CVE Test Only:

mvn test -Dtest=CVE202548924Test

References

Official Resources

Related Information

  • CWE-674: Uncontrolled Recursion
  • Apache Commons Lang 3.18.0: Official release with fix
  • Original Issue: Reported vulnerability in class name resolution

Migration Guide

For Users of commons-lang 2.6

If you're using commons-lang 2.6 and cannot upgrade to commons-lang3 3.18.0, you can use this patched version:

  1. Build the Fixed JAR:

    git clone <your-fork-url>
    cd commons-lang
    git checkout CVE-2025-48924
    mvn clean package -DskipTests
  2. Replace Your Dependency:

    • Copy target/commons-lang-2.6-CVE-2025-48924.jar to your project
    • Update your dependency management to use the patched JAR
  3. Verify the Fix:

    • Run your application's test suite
    • Verify no breaking changes (API is fully compatible)

Recommended Approach

For new projects or major updates, upgrade to Apache Commons Lang 3.18.0 or later to receive the official fix along with other improvements and bug fixes.

Commit History

  • Commit 9be2350a5: Fix CVE-2025-48924: Eliminate uncontrolled recursion in ClassUtils.getClass()

    • Replaced recursive implementation with iterative do-while loop
    • Added comprehensive security documentation
    • Validation: All 1,974 tests passing
    • Author: Jinwoo Hwang
  • Commit 5f75d7307: Add comprehensive CVE-2025-48924 security test

    • 221-line test with dynamic depth calculation
    • Author: Jinwoo Hwang

Development Environment

  • JUnit Version: 3.8.1
  • Build Tool: Apache Maven

Security Considerations

Attack Vectors

  1. User Input: Applications that pass user-controlled strings to ClassUtils.getClass()
  2. Configuration Files: XML/JSON parsers that use Commons Lang for class resolution
  3. Reflection APIs: Dynamic class loading based on external input

Mitigation Strategies

  1. Apply This Fix: Use the patched version or upgrade to commons-lang3 3.18.0+
  2. Input Validation: Sanitize class names before passing to getClass()
  3. Depth Limiting: Although fixed, consider validating reasonable nesting levels
  4. Error Handling: Implement proper error handling for ClassNotFoundException

License

This fix maintains the original Apache License 2.0 of the Apache Commons Lang project.

Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Contact & Contributions

This is a security remediation branch for CVE-2025-48924 in a forked repository.

  • Repository: sassoftware/commons-lang
  • Branch: CVE-2025-48924
  • Fix Author: Jinwoo Hwang

For the official Apache Commons Lang project, visit: https://commons.apache.org/proper/commons-lang/


Last Updated: November 10, 2025
Fix Version: commons-lang 2.6-CVE-2025-48924
Status: ✅ Fully Tested and Validated

About

Apache Commons Lang

Resources

License

Security policy

Stars

Watchers

Forks

Packages

No packages published

Contributors 15