This branch contains the remediation of the security vulnerability reported in CVE-2025-48924, an Uncontrolled Recursion vulnerability in Apache Commons Lang.
- CVE ID: CVE-2025-48924
- Type: Uncontrolled Recursion (CWE-674)
- Severity: High
- Published: July 11, 2025
- CVSS Score: 7.5
commons-lang:commons-lang2.0 through 2.6org.apache.commons:commons-lang33.0 through 3.17.x
org.apache.commons:commons-lang33.18.0 (official Apache fix)- This branch:
commons-lang2.6 with this fix
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.
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:
-
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
StackOverflowErroris anErrorand typically unhandled by applications, this results in immediate application termination. -
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.
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);
}- Eliminated Recursion: Replaced recursive implementation with iterative
do-whileloop - No Depth Limiting: No maximum depth constant needed - stack overflow impossible
- Same Behavior: Maintains identical API and exception handling
- No Breaking Changes: Fully backward compatible
-
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)
- Lines 738-778: Replaced recursive
-
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
-Xssand-XX:ThreadStackSizeJVM 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
- Parses
-
Multi-Threat Detection: Tests for both vulnerability manifestations:
StackOverflowError: Primary threat from recursive calls exhausting thread stackOutOfMemoryError: 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):
StackOverflowErrororOutOfMemoryError
-
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
- Pre-fix (vulnerable): FAILED in ~39.5 seconds with
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
StackOverflowErrororOutOfMemoryError - Post-fix (remediated): PASSED in 41.5s with
ClassNotFoundException
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)mvn clean package -DskipTestsOutput:
target/commons-lang-2.6-CVE-2025-48924.jar- Build Status: SUCCESS
Full Test Suite:
mvn testCVE Test Only:
mvn test -Dtest=CVE202548924Test- NVD Entry: https://nvd.nist.gov/vuln/detail/CVE-2025-48924
- Apache Security Advisory: https://lists.apache.org/thread/bgv0lpswokgol11tloxnjfzdl7yrc1g1
- OSS Security Mailing List: http://www.openwall.com/lists/oss-security/2025/07/11/1
- CWE-674: Uncontrolled Recursion
- Apache Commons Lang 3.18.0: Official release with fix
- Original Issue: Reported vulnerability in class name resolution
If you're using commons-lang 2.6 and cannot upgrade to commons-lang3 3.18.0, you can use this patched version:
-
Build the Fixed JAR:
git clone <your-fork-url> cd commons-lang git checkout CVE-2025-48924 mvn clean package -DskipTests
-
Replace Your Dependency:
- Copy
target/commons-lang-2.6-CVE-2025-48924.jarto your project - Update your dependency management to use the patched JAR
- Copy
-
Verify the Fix:
- Run your application's test suite
- Verify no breaking changes (API is fully compatible)
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 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
- JUnit Version: 3.8.1
- Build Tool: Apache Maven
- User Input: Applications that pass user-controlled strings to
ClassUtils.getClass() - Configuration Files: XML/JSON parsers that use Commons Lang for class resolution
- Reflection APIs: Dynamic class loading based on external input
- Apply This Fix: Use the patched version or upgrade to commons-lang3 3.18.0+
- Input Validation: Sanitize class names before passing to
getClass() - Depth Limiting: Although fixed, consider validating reasonable nesting levels
- Error Handling: Implement proper error handling for
ClassNotFoundException
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.
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