Severity: CRITICAL
File: MavenRepositoryClassSource.java
Problem
Same bugs as MavenNexusClassSource (Issue #59 ): silent exception swallowing, no timeouts, no size limits. Also has the same TOCTOU bug that was already reported in Issue #58 .
Bug Details
Lines 76-85: Silent exception swallowing
for (MavenArtifact artifact : artifacts ) {
try {
String jarUrl = buildJarUrl (artifact );
byte [] classData = extractClassFromJar (jarUrl , classFileName );
classCache .put (cacheKey , classData );
return classData ;
} catch (IOException e ) {
// Continue to next artifact if class not found in this one
}
}
throw new IOException ("Class not found in any configured Maven artifacts: " + className );
Problem : Identical to Issue #59 - all errors are silently discarded
When loading fails, you get:
Class not found in any configured Maven artifacts: com.example.MyClass
No indication whether:
Maven Central is down
Wrong artifact coordinates
Network timeout
Auth failure
Corrupted JAR
Lines 110-139: extractClassFromJar() critical bugs
1. Line 112: No timeout
HttpURLConnection connection = (HttpURLConnection ) url .openConnection ();
Can hang forever - same as Issue #53
2. Lines 127-133: No size validation
ByteArrayOutputStream out = new ByteArrayOutputStream ();
byte [] buffer = new byte [DEFAULT_BUFFER_SIZE ];
int bytesRead ;
while ((bytesRead = jarIn .read (buffer )) != -1 ) {
out .write (buffer , 0 , bytesRead );
}
return out .toByteArray ();
Can OOM - same as Issues #51 -54
3. Line 122: Downloads entire JAR streamed to memory
No Content-Length check before streaming JAR
Lines 70-72: TOCTOU race condition
String cacheKey = className ;
if (classCache .containsKey (cacheKey )) {
return classCache .get (cacheKey ); // ← Can return null!
}
Already reported in Issue #58 - uses containsKey() + get() pattern which has race condition.
Note : MavenNexusClassSource FIXED this bug (line 76 uses atomic get()), but MavenRepositoryClassSource still has it.
Required Fixes
Fix 1: Use atomic get() instead of containsKey()
@ Override
public byte [] loadClassData (String className ) throws IOException {
// ATOMIC - fixes TOCTOU race from Issue #58
byte [] cachedData = classCache .get (className );
if (cachedData != null ) {
return cachedData ;
}
String classFileName = ClassNameUtil .toClassFilePath (className );
List <String > errorMessages = new ArrayList <>();
for (MavenArtifact artifact : artifacts ) {
try {
String jarUrl = buildJarUrl (artifact );
byte [] classData = extractClassFromJar (jarUrl , classFileName );
classCache .put (className , classData );
return classData ;
} catch (IOException e ) {
// Accumulate errors instead of silently swallowing
String errorMsg = String .format ("Artifact %s - %s" ,
artifact .toString (), e .getMessage ());
errorMessages .add (errorMsg );
if (logger .isDebugEnabled ()) {
logger .debug ("Failed to load {} from {}" , className , artifact , e );
}
}
}
// Detailed error message
String allErrors = String .join ("\n - " , errorMessages );
throw new IOException (
"Class not found in any of " + artifacts .size () + " configured Maven artifacts: " +
className + "\n Attempted artifacts:\n - " + allErrors
);
}
Fix 2: Add timeouts and size validation
private byte [] extractClassFromJar (String jarUrl , String classFileName ) throws IOException {
URL url = new URL (jarUrl );
HttpURLConnection connection = (HttpURLConnection ) url .openConnection ();
connection .setConnectTimeout (10000 ); // 10 seconds
connection .setReadTimeout (30000 ); // 30 seconds
AuthHelper .configureAuth (connection , authConfig );
connection .setRequestMethod ("GET" );
int responseCode = connection .getResponseCode ();
if (responseCode != HttpURLConnection .HTTP_OK ) {
throw new IOException ("HTTP " + responseCode + " for JAR: " + jarUrl );
}
// Check JAR size before downloading
long contentLength = connection .getContentLengthLong ();
if (contentLength > MAX_JAR_SIZE ) {
throw new IOException (
"JAR too large: " + contentLength + " bytes (max " + MAX_JAR_SIZE + ")"
);
}
try (InputStream in = connection .getInputStream ();
JarInputStream jarIn = new JarInputStream (in )) {
JarEntry entry ;
while ((entry = jarIn .getNextJarEntry ()) != null ) {
if (entry .getName ().equals (classFileName ) && !entry .isDirectory ()) {
long size = entry .getSize ();
if (size > MAX_CLASS_SIZE ) {
throw new IOException (
"Class too large: " + size + " bytes (max " + MAX_CLASS_SIZE + ")"
);
}
// Read with size enforcement
ByteArrayOutputStream out = new ByteArrayOutputStream ();
byte [] buffer = new byte [DEFAULT_BUFFER_SIZE ];
long totalRead = 0 ;
int bytesRead ;
while ((bytesRead = jarIn .read (buffer )) != -1 ) {
totalRead += bytesRead ;
if (totalRead > MAX_CLASS_SIZE ) {
throw new IOException ("Class exceeded size limit: " + totalRead );
}
out .write (buffer , 0 , bytesRead );
}
return out .toByteArray ();
}
}
}
throw new IOException ("Class not found in JAR: " + classFileName + " (URL: " + jarUrl + ")" );
}
Impact
Current bugs :
Silent exception swallowing - impossible to debug
TOCTOU race condition - random NPEs (duplicate of Issue CRITICAL: TOCTOU race condition in cache checks causes NullPointerException #58 )
No timeouts - threads hang forever
No size limits - OOM crashes
With fixes :
Detailed error messages showing all failure reasons
Thread-safe cache access
Bounded resource usage
Production-ready reliability
Related Issues
Severity: CRITICAL
File: MavenRepositoryClassSource.java
Problem
Same bugs as MavenNexusClassSource (Issue #59): silent exception swallowing, no timeouts, no size limits. Also has the same TOCTOU bug that was already reported in Issue #58.
Bug Details
Lines 76-85: Silent exception swallowing
Problem: Identical to Issue #59 - all errors are silently discarded
When loading fails, you get:
No indication whether:
Lines 110-139: extractClassFromJar() critical bugs
1. Line 112: No timeout
Can hang forever - same as Issue #53
2. Lines 127-133: No size validation
Can OOM - same as Issues #51-54
3. Line 122: Downloads entire JAR streamed to memory
No Content-Length check before streaming JAR
Lines 70-72: TOCTOU race condition
Already reported in Issue #58 - uses containsKey() + get() pattern which has race condition.
Note: MavenNexusClassSource FIXED this bug (line 76 uses atomic get()), but MavenRepositoryClassSource still has it.
Required Fixes
Fix 1: Use atomic get() instead of containsKey()
Fix 2: Add timeouts and size validation
Impact
Current bugs:
With fixes:
Related Issues