Description
JNDI resolves objects and contexts by name. If untrusted input supplies the name for lookup, lookupLink or InitialContext.doLookup, an attacker can select the resource identifier that the application resolves.
InitialContext treats a string shaped like scheme_id:... as a URL name and looks for that scheme's URL context factory. LDAP, RMI, DNS or a custom provider may therefore cause unintended network connections, resource access, information disclosure or delays. Reconstructing a returned reference as an object may also lead to code execution, depending on the JDK, provider, object factories, classpath and serialization settings.
The protections in newer JDKs have specific limits. JDK 24 permanently disabled remote factory-class downloading in the built-in LDAP/RMI providers and removed the old trustURLCodebase properties. JDK 25's built-in LDAP provider does not reconstruct serialized data and related references unless com.sun.jndi.ldap.object.trustSerialData is explicitly true. These protections do not eliminate URL-triggered network access or risks from local factories, custom providers and a custom ObjectFactoryBuilder.
Potential impact
- Server-side connections to attacker-selected LDAP, RMI, DNS or custom providers
- Access to internal naming services or disclosure of resources behind a firewall
- Thread and connection exhaustion caused by slow or unresponsive providers
- Object-creation side effects or code execution with unsafe legacy, serialization or factory configurations
Remediation
- Keep complete JNDI names under developer control. Accept a business key and map it through a closed
switch, enum or equivalent mapping to a fixed local name. Never append an untrusted suffix. - If callers must supply names, compare them exactly against a finite set of reviewed complete local names. Prefix checks, regexes or scheme denylists such as
ldap:andrmi:do not establish every possible provider or federated destination. - Fix
Context.INITIAL_CONTEXT_FACTORY,Context.PROVIDER_URL,Context.OBJECT_FACTORIES,Context.URL_PKG_PREFIXESand provider settings in trusted deployment configuration. Keep only trusted providers and factories on the classpath and review customObjectFactoryBuilderimplementations separately. - Use a supported, updated JDK 25. Removed
trustURLCodebaseproperties are not a remedy. Keep LDAPtrustSerialDatadisabled and restrictjdk.jndi.object.factoriesFilterand provider-specific filters to necessary factories. - Restrict outbound access to required naming servers and use least-privilege credentials. For the built-in LDAP provider, configure
com.sun.jndi.ldap.connect.timeoutandcom.sun.jndi.ldap.read.timeout. These reduce impact but do not make attacker-controlled names safe.
Examples
Before
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.http.HttpServletRequest;
class UnsafeJndiLookup {
Object lookup(HttpServletRequest request) throws NamingException {
String name = request.getParameter("name");
Context context = new InitialContext();
return context.lookup(name); // BAD: request input can select a provider and resource
}
}
After
Map the external key to a complete application-owned local name. The switch result contains no request text.
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.http.HttpServletRequest;
class SafeJndiLookup {
Object lookup(HttpServletRequest request) throws NamingException {
String key = request.getParameter("name");
if (key == null) {
throw new NamingException("resource not selected");
}
String jndiName = switch (key) {
case "mainDs" -> "java:comp/env/jdbc/MainDS";
case "ordersQ" -> "java:comp/env/jms/OrdersQueue";
default -> throw new NamingException("resource not allowed");
};
return new InitialContext().lookup(jndiName);
}
}
References
- Java SE 25
ContextAPI - Java SE 25 InitialContext API
- Java SE 25
java.namingModule - JDK-8338536: Permanently Disable Remote Code Downloading in JNDI
- JDK 25.0.4.1 Release Notes
- Oracle JNDI: URL Context Factory
- Oracle JNDI: Security
- CWE-99: Improper Control of Resource Identifiers
- OWASP Top 10:2025 A05 Injection
- OWASP Top 10:2021 A03 Injection
- OWASP ASVS 5.0