Executive Summary
A critical remote code execution vulnerability (CVE-2026-41635, CVSS 9.8) has been disclosed in Apache MINA, the widely used Java network application framework. The vulnerability resides in AbstractIoBuffer.resolveClass(), the method responsible for resolving class names during deserialization of network data. An internal branching logic intended to handle static classes and primitive types skips the classname allowlist check entirely, allowing an attacker to bypass MINA's deserialization protection and execute arbitrary code by sending a crafted serialized payload over the network.
Apache MINA is used in a wide range of networked Java applications including Apache FtpServer, Apache SSHD, and numerous enterprise network services that implement custom binary protocols.
Vulnerability Overview
| Attribute | Value |
|---|---|
| CVE ID | CVE-2026-41635 |
| CVSS Score | 9.8 (Critical) |
| CVSS Vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| Attack Vector | Network |
| Attack Complexity | Low |
| Privileges Required | None |
| User Interaction | None |
| Scope | Unchanged |
| Confidentiality / Integrity / Availability | High / High / High |
| Root Cause | Branching logic in resolveClass() bypasses allowlist for static/primitive types |
| Affected Component | AbstractIoBuffer.resolveClass() |
| Patch Available | Yes — see Apache advisory |
| Published | April 27, 2026 |
Technical Analysis
Root Cause: Branching Logic That Skips Allowlist
Apache MINA's AbstractIoBuffer provides buffer management for reading and writing data over network connections. When deserializing objects from a network buffer, resolveClass() is called to map the serialized class descriptor to a Java class. MINA added a classname allowlist to restrict which classes may be instantiated during deserialization — a sound defense against gadget chain attacks.
However, resolveClass() contains two branches:
// Simplified representation of the vulnerable code pattern
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
String className = desc.getName();
// Branch 1: Static classes or primitive types
if (isStaticOrPrimitive(className)) {
// BUG: Returns class directly WITHOUT checking the allowlist
return Class.forName(className);
}
// Branch 2: Normal classes — allowlist IS checked
if (!allowedClasses.contains(className)) {
throw new InvalidClassException("Class not in allowlist: " + className);
}
return Class.forName(className);
}An attacker can craft a serialized payload where the malicious class descriptor is processed through Branch 1 (the static/primitive branch), which resolves and instantiates the class without any allowlist check. This completely bypasses MINA's deserialization protection.
The fix, as described in the Apache advisory, ensures that all classes — including those categorized as static or primitive — are verified against the accepted class filter before instantiation.
What Makes "Static or Primitive" Classes Dangerous
In Java's serialization model, certain metadata about static fields and primitive types is encoded in the serialized stream. An attacker who controls the serialized payload can:
- Craft a class descriptor that triggers the "static/primitive" code path
- Embed a reference to a malicious class that is present on the MINA server's classpath
- When MINA deserializes the payload,
resolveClass()resolves the malicious class via Branch 1 - The resolved class is instantiated during deserialization, triggering the gadget chain
Attack Flow
1. Attacker identifies a network service built on Apache MINA
(FTP server, SSH server, custom binary protocol listener)
2. Attacker crafts a serialized Java payload that:
- Encodes the malicious class reference in the "static/primitive" branch path
- Embeds a gadget chain class available on the server classpath
3. Attacker sends the crafted payload over the network to the MINA listener
4. AbstractIoBuffer.resolveClass() processes the class descriptor:
- isStaticOrPrimitive() returns true
- Allowlist check is SKIPPED
- Class.forName(maliciousClassName) instantiates the gadget chain class
5. Gadget chain executes during deserialization:
- Arbitrary OS commands run as the MINA service account
6. Attacker achieves full remote code executionAffected Deployments
Any service built on Apache MINA that:
- Accepts serialized Java objects over the network
- Relies on
AbstractIoBufferfor data reading - Processes untrusted network input
is potentially exploitable. Common affected deployments include:
| Deployment | Description |
|---|---|
| Apache FtpServer | Built on MINA — widely deployed FTP daemon |
| Apache SSHD | Java SSH server implementation using MINA |
| Custom MINA Services | Enterprise applications with custom binary protocol servers |
| IoT / Embedded Network Services | MINA used in embedded Java network applications |
Impact Assessment
| Impact Area | Description |
|---|---|
| Remote Code Execution | Unauthenticated code execution as the service account |
| Server Takeover | Full control of the underlying host if the service runs as a privileged user |
| Data Exfiltration | Access to all data accessible to the MINA service process |
| Persistence | Attacker can install backdoors before the vulnerability is patched |
| Lateral Movement | Compromised FTP/SSH servers are frequently used as pivots into internal networks |
| Wide Attack Surface | MINA underpins multiple Apache Foundation projects used across enterprise environments |
Remediation
Step 1: Upgrade Apache MINA
Apply the patched version released by Apache. The fix ensures the allowlist check is applied in both branches of resolveClass().
<!-- Maven -->
<dependency>
<groupId>org.apache.mina</groupId>
<artifactId>mina-core</artifactId>
<version>PATCHED_VERSION</version>
</dependency>// Gradle
implementation 'org.apache.mina:mina-core:PATCHED_VERSION'If using Apache FtpServer or Apache SSHD, also upgrade those to versions that bundle the patched MINA release.
Step 2: Restrict Network Access as an Immediate Mitigation
If patching cannot be applied immediately, restrict access to MINA-based service ports to trusted IP ranges only:
# Block untrusted access to MINA service port (example: FTP on 21)
iptables -I INPUT -p tcp --dport 21 -s 0.0.0.0/0 -j DROP
iptables -I INPUT -p tcp --dport 21 -s TRUSTED_CIDR -j ACCEPT
# Or use firewalld
firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" \
source address="TRUSTED_CIDR" port port="21" protocol="tcp" accept' --permanent
firewall-cmd --reloadStep 3: Apply a Custom resolveClass Override
As a temporary workaround, subclass the vulnerable MINA buffer class and override resolveClass() to enforce allowlist checking in all code paths:
public class HardenedIoBuffer extends AbstractIoBuffer {
private final Set<String> allowedClasses;
@Override
protected Class<?> resolveClass(ObjectStreamClass desc)
throws IOException, ClassNotFoundException {
String className = desc.getName();
// Always check the allowlist — no exceptions for static/primitive
if (!allowedClasses.contains(className)) {
throw new InvalidClassException(
"Deserialization rejected: class not in allowlist: " + className
);
}
return super.resolveClass(desc);
}
}Step 4: Apply a JVM-Level Serialization Filter
Configure a global ObjectInputFilter to restrict deserialization across the entire JVM:
# JVM startup argument
-Djdk.serialFilter=java.base/**;java.util.**;!*Step 5: Audit for Compromise
# Search MINA service logs for deserialization-related errors or anomalies
grep -i "deserializ\|resolveClass\|InvalidClassException" /var/log/ftpserver/*.log
# Check for unexpected processes spawned by the MINA service
ps auxf | grep -A5 java
# Review outbound network connections from the service host
ss -tnp | grep ESTABLISHEDDetection Indicators
| Indicator | Description |
|---|---|
InvalidClassException errors with unusual class names in logs | Attacker probing — allowlist partially working |
| Unexpected child processes spawned from MINA service JVM | Successful gadget chain execution |
| Outbound connections to unknown hosts from service server | Post-exploitation C2 or data exfiltration |
| Unfamiliar binaries or scripts appearing on service host | Attacker staging payloads |
| New administrative accounts or SSH keys on service host | Persistence installation |
Post-Remediation Checklist
- Upgrade Apache MINA core to the patched version
- Upgrade Apache FtpServer, SSHD, and any other MINA-based services to patched versions
- Apply JVM-level serialization filters as a defense-in-depth measure
- Restrict network access to MINA service ports to trusted IP ranges
- Audit service logs for pre-patch exploitation indicators
- Inspect host file system for unexpected binaries, scripts, or cron jobs
- Rotate all service account credentials and SSH keys on affected hosts
- Review network egress logs for anomalous outbound connections
- Verify patch application by checking the MINA version bundled in deployed artifacts