June 10, 2025·6 min read·engineeringkafkasecurityconnect

Kafka restricts JAAS login modules after an LDAP deserialization disclosure

CVE-2025-27818 shows how delegated SASL configuration can become LDAP access and possible code execution in the worker JVM.

Permission to configure a connector's Kafka client can become permission to select code that runs inside the Connect worker. CVE-2025-27818 exposes that boundary through the JAAS LDAP login module. A configuration accepted for authentication can cause the server to contact an attacker-controlled LDAP service and deserialize its response.

Kafka's security advisory dates its announcement to June 9. The CVE record published June 10 explains the required configuration access and the affected versions. Kafka 3.9.1 and 4.0.0 disable the problematic modules by default.

I value Kafka's independent consumers and replayable history, but connector configuration is a separate authority boundary. Giving someone access to define a data flow should not silently imply that they may select arbitrary authentication code with the worker's capabilities.

JAAS configuration selects a class

The vulnerable property is sasl.jaas.config. Its role goes beyond choosing a username or an endpoint. The parser in Kafka 3.9.1 interprets a login module class, a control flag, and a set of options.

That format makes the class name part of the configuration's meaning. The parser creates an application configuration entry describing that module and its options. A security assessment therefore needs to consider which classes the configuration can select, not just whether the text has valid syntax.

The disclosure concerns selecting com.sun.security.auth.module.LdapLoginModule. Kafka says this can cause a connection to the attacker's LDAP server and deserialization of the response. If suitable gadget chains exist on the classpath, the response can lead to code execution.

Those conditions matter. The advisory does not describe arbitrary Kafka record contents automatically executing Java code. The initiating input is authentication configuration controlled by an operator with the relevant access. Its classpath then affects what deserializing the untrusted response can do.

The distinction also explains why connector dependencies enter the remediation advice. A worker's available classes influence the consequence of deserialization. The same permitted network interaction can have a different impact depending on which deserialization behavior the loaded dependencies make available.

Connector overrides delegate worker behavior

Kafka names three connector configuration paths. They apply the JAAS property to producer, consumer, and administrative clients through their respective override prefixes. Each path can bring the selected login module into a client used by the worker.

That is a useful reminder that a connector is not only its user-visible source or sink definition. It also uses Kafka clients, and those clients have authentication behavior. Allowing arbitrary overrides delegates control over that behavior to the person supplying the connector configuration.

The CVE describes access to alter cluster configuration or access to a Connect worker with permission to create or modify connectors. For Connect, the configuration must permit arbitrary relevant SASL JAAS settings and a SASL-based security protocol. These are access conditions, not incidental implementation details.

The record also distinguishes defaults across versions. Since Kafka 3.0.0, the relevant connector properties can be supplied in out-of-the-box Connect configurations. Earlier versions require a connector client override policy that permits them.

That means the same connector configuration permission can have a different practical scope depending on the worker's version and policy. A statement that a user can edit connectors is incomplete unless it also describes which client settings the worker accepts from that user.

The vulnerability entry lists versions 2.3.0 through 3.9.0 as affected. Its broader narrative also discusses broker configuration paths. The useful operational question is whether an untrusted configuration author can reach the named module selection path in the actual deployment.

The attack crosses into a more privileged process

The worker performs the LDAP operation. The configuration author does not need to run a separate program inside the worker JVM if the accepted login module causes that JVM to act on the supplied settings. Its existing capabilities become available to the selected authentication mechanism.

This is why configuration validation is a security control rather than only a usability feature. A syntactically valid configuration can request behavior outside the authority intended for its author. Valid text and authorized behavior are different properties.

The LDAP response then provides another boundary. It is data supplied by a remote party, but deserialization can interpret it through classes available in the local process. The potential code-execution outcome depends on that interaction, which is why the advisory explicitly qualifies it with available gadget chains.

It would be inaccurate to say the flaw guarantees code execution in every affected worker. The public account establishes an untrusted deserialization path and possible code execution under the stated dependency conditions. It does not identify every worker's classpath or prove the presence of a usable chain there.

It would also be inaccurate to call the initiating access unauthenticated simply because the remote LDAP server is attacker-controlled. Kafka describes an authenticated operator with relevant configuration access. The escalation concerns the authority that configuration access can exercise inside the worker.

The fixed versions restrict module selection

Kafka introduces the JVM system property org.apache.kafka.disallowed.login.modules to prevent problematic modules being used in SASL JAAS configuration. The advisory says both JndiLoginModule and LdapLoginModule are disabled by default in Connect 3.9.1 and 4.0.0.

A JVM argument can express the documented restriction. This example names both modules identified by the advisory and does not provide an LDAP connection configuration.

-Dorg.apache.kafka.disallowed.login.modules=com.sun.security.auth.module.JndiLoginModule,com.sun.security.auth.module.LdapLoginModule

The control acts on module selection. It prevents the configuration from invoking the named implementation through the affected mechanism. That is a different intervention from attempting to recognize every malicious serialized response after the connection has already occurred.

The default is consequential because it changes what an otherwise ordinary worker accepts. An operator upgrading to the fixed version receives a restriction on the named modules without needing to invent a separate connector-specific filtering convention.

A deployment that intentionally changes the restriction needs to account for the behavior it re-enables. The existence of a system property does not make any chosen value equally protective. The named defaults correspond to the problematic modules identified in the disclosure.

An earlier JNDI issue explains the broader restriction

Kafka's advisory list also documents CVE-2023-25194. That earlier issue involved JndiLoginModule selected through Connect's SASL JAAS configuration and possible denial of service or code execution through JNDI requests.

The history matters because the newer disclosure is not a reason to treat every Java-provided login module as an innocuous credential parser. Different modules can perform network operations and interpret responses inside the worker process. Restricting only a previously identified route does not establish that another module has the same safe behavior.

The June fix explicitly names both modules in the default restriction. That broadens the supplied policy across the two named mechanisms. It still leaves the application responsible for deciding which configuration authors and authentication arrangements it trusts.

My preference is to preserve the distinction between a connector's business purpose and its worker-level capabilities. A data integration may need credentials for a specific service. That requirement does not imply a need for unrestricted module selection or arbitrary network destinations.

Override policy remains an independent control

The CVE recommends validating connector configurations and allowing only trusted LDAP arrangements. It also names custom connector client override policies as a way to control which Kafka client properties a connector may replace. Those policies act before a configuration becomes behavior inside the worker.

Dependency maintenance addresses another part of the path. Upgrading a vulnerable connector dependency or removing an unnecessary connector can change the available deserialization classes. That does not replace the value of preventing an untrusted author from selecting the problematic module in the first place.

The controls therefore concern different facts. Module restrictions constrain selected authentication code. Override policy constrains delegated configuration, while dependency updates constrain code present in the process. None of those facts can be inferred solely from a user's ability to authenticate to the Connect REST API.

The disclosure gives configuration access a more precise meaning. A worker accepting arbitrary SASL JAAS overrides delegates code selection and network behavior, not merely a credential string. Kafka 3.9.1 and 4.0.0 narrow that delegation by disabling the named modules, with explicit policy controls available for deployments that need to constrain overrides further.