Apache Flume prior to 1.11.0 has an Improper Input Validation (JNDI Injection) in JMSSource
Description
Apache Flume 1.4.0 to 1.10.1 allows remote code execution via JMS Source due to unsafe JNDI providerURL, fixed by restricting JNDI protocols to 'java'.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Apache Flume 1.4.0 to 1.10.1 allows remote code execution via JMS Source due to unsafe JNDI providerURL, fixed by restricting JNDI protocols to 'java'.
Vulnerability
Overview
CVE-2022-42468 is a remote code execution vulnerability in Apache Flume, affecting versions 1.4.0 through 1.10.1. The flaw resides in the JMS Source component, which lacks proper validation of the JNDI provider URL (providerURL). When an attacker can control this configuration parameter, they can supply a malicious JNDI URI referencing an attacker-controlled LDAP or RMI server, leading to arbitrary code execution via JNDI injection [1][2][3].
Exploitation
Mechanism
The vulnerability is triggered when a Flume agent is configured to use a JMS Source with an unsafe providerURL. An attacker with the ability to modify this configuration—for instance, by compromising the configuration store or tricking an administrator into applying a malicious configuration—can specify a JNDI URI that uses protocols such as LDAP or RMI. On lookup, the JNDI client fetches a remote object, which can execute arbitrary Java code on the Flume agent [1][3]. No authentication is required beyond the ability to set the configuration value.
Impact
Successful exploitation grants an attacker full remote code execution on the machine running the affected Apache Flume instance. This could allow the attacker to compromise the log data pipeline, access sensitive data, pivot to other systems, or use the compromised host as a foothold for further attacks [2][3].
Mitigation
Apache Flume 1.11.0 and later include a fix that adds a new JVM system property, JndiAllowedProtocols, which by default restricts JNDI lookups to only the java protocol. The fix validates the scheme of the JNDI URI against this whitelist [1][3]. Users unable to upgrade immediately should ensure that the providerURL in JMS Source configurations is never set from untrusted input and apply appropriate network controls. The issue was resolved in October 2022 via commit eee179a [1].
AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
org.apache.flume.flume-ng-sources:flume-jms-sourceMaven | < 1.11.0 | 1.11.0 |
Affected products
2- Apache Software Foundation/Apache Flumev5Range: Flume JMSSource
Patches
1eee179a09df4FLUME-3437 - Improve JMSSource validation
5 files changed · +46 −46
flume-ng-sources/flume-jms-source/src/main/java/org/apache/flume/source/jms/JMSMessageConsumer.java+1 −15 modified@@ -35,14 +35,11 @@ import javax.jms.Topic; import javax.naming.InitialContext; import javax.naming.NamingException; -import java.net.URI; -import java.net.URISyntaxException; import java.util.ArrayList; import java.util.List; class JMSMessageConsumer { private static final Logger logger = LoggerFactory.getLogger(JMSMessageConsumer.class); - private static final String JAVA_SCHEME = "java"; private final int batchSize; private final long pollTimeout; @@ -102,14 +99,7 @@ class JMSMessageConsumer { throw new IllegalStateException(String.valueOf(destinationType)); } } else { - try { - URI uri = new URI(destinationName); - String scheme = uri.getScheme(); - assertTrue(scheme == null || scheme.equals(JAVA_SCHEME), - "Unsupported JNDI URI: " + destinationName); - } catch (URISyntaxException ex) { - logger.warn("Invalid JNDI URI - {}", destinationName); - } + JMSSource.verifyContext(destinationName); destination = (Destination) initialContext.lookup(destinationName); } } catch (JMSException e) { @@ -220,8 +210,4 @@ void close() { logger.error("Could not destroy connection", e); } } - - private void assertTrue(boolean arg, String msg) { - Preconditions.checkArgument(arg, msg); - } }
flume-ng-sources/flume-jms-source/src/main/java/org/apache/flume/source/jms/JMSMessageConverter.java+3 −3 modified@@ -39,13 +39,13 @@ @InterfaceStability.Stable public interface JMSMessageConverter { - public List<Event> convert(Message message) throws JMSException; + List<Event> convert(Message message) throws JMSException; /** * Implementors of JMSMessageConverter must either provide * a suitable builder or implement the Configurable interface. */ - public interface Builder { - public JMSMessageConverter build(Context context); + interface Builder { + JMSMessageConverter build(Context context); } }
flume-ng-sources/flume-jms-source/src/main/java/org/apache/flume/source/jms/JMSSource.java+40 −28 modified@@ -21,6 +21,8 @@ import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.Properties; @@ -56,6 +58,7 @@ public class JMSSource extends AbstractPollableSource implements BatchSizeSupported { private static final Logger logger = LoggerFactory.getLogger(JMSSource.class); private static final String JAVA_SCHEME = "java"; + public static final String JNDI_ALLOWED_PROTOCOLS = "JndiAllowedProtocols"; // setup by constructor private final InitialContextFactory initialContextFactory; @@ -82,6 +85,7 @@ public class JMSSource extends AbstractPollableSource implements BatchSizeSuppor private int jmsExceptionCounter; private InitialContext initialContext; + private static List<String> allowedSchemes = getAllowedProtocols(); public JMSSource() { this(new InitialContextFactory()); @@ -92,6 +96,34 @@ public JMSSource(InitialContextFactory initialContextFactory) { this.initialContextFactory = initialContextFactory; } + private static List<String> getAllowedProtocols() { + String allowed = System.getProperty(JNDI_ALLOWED_PROTOCOLS, null); + if (allowed == null) { + return Collections.singletonList(JAVA_SCHEME); + } else { + String[] items = allowed.split(","); + List<String> schemes = new ArrayList<>(); + schemes.add(JAVA_SCHEME); + for (String item : items) { + if (!item.equals(JAVA_SCHEME)) { + schemes.add(item.trim()); + } + } + return schemes; + } + } + + public static void verifyContext(String location) { + try { + String scheme = new URI(location).getScheme(); + if (scheme != null && !allowedSchemes.contains(scheme)) { + throw new IllegalArgumentException("Invalid JNDI URI: " + location); + } + } catch (URISyntaxException ex) { + logger.trace("{}} is not a valid URI", location); + } + } + @Override protected void doConfigure(Context context) throws FlumeException { sourceCounter = new SourceCounter(getName()); @@ -100,14 +132,7 @@ protected void doConfigure(Context context) throws FlumeException { JMSSourceConfiguration.INITIAL_CONTEXT_FACTORY, "").trim(); providerUrl = context.getString(JMSSourceConfiguration.PROVIDER_URL, "").trim(); - try { - URI uri = new URI(providerUrl); - String scheme = uri.getScheme(); - assertTrue(scheme == null || scheme.equals(JAVA_SCHEME), - "Unsupported JNDI URI: " + providerUrl); - } catch (URISyntaxException ex) { - logger.warn("Invalid JNDI URI - {}", providerUrl); - } + verifyContext(providerUrl); destinationName = context.getString(JMSSourceConfiguration.DESTINATION_NAME, "").trim(); @@ -190,14 +215,7 @@ protected void doConfigure(Context context) throws FlumeException { String connectionFactoryName = context.getString( JMSSourceConfiguration.CONNECTION_FACTORY, JMSSourceConfiguration.CONNECTION_FACTORY_DEFAULT).trim(); - try { - URI uri = new URI(connectionFactoryName); - String scheme = uri.getScheme(); - assertTrue(scheme == null || scheme.equals(JAVA_SCHEME), - "Unsupported JNDI URI: " + connectionFactoryName); - } catch (URISyntaxException ex) { - logger.warn("Invalid JNDI URI - {}", connectionFactoryName); - } + verifyContext(connectionFactoryName); assertNotEmpty(initialContextFactoryName, String.format( "Initial Context Factory is empty. This is specified by %s", @@ -291,10 +309,6 @@ private void assertNotEmpty(String arg, String msg) { Preconditions.checkArgument(!arg.isEmpty(), msg); } - private void assertTrue(boolean arg, String msg) { - Preconditions.checkArgument(arg, msg); - } - @Override protected synchronized Status doProcess() throws EventDeliveryException { boolean error = true; @@ -322,14 +336,12 @@ protected synchronized Status doProcess() throws EventDeliveryException { sourceCounter.incrementChannelWriteFail(); } catch (JMSException jmsException) { logger.warn("JMSException consuming events", jmsException); - if (++jmsExceptionCounter > errorThreshold) { - if (consumer != null) { - logger.warn("Exceeded JMSException threshold, closing consumer"); - sourceCounter.incrementEventReadFail(); - consumer.rollback(); - consumer.close(); - consumer = null; - } + if (++jmsExceptionCounter > errorThreshold && consumer != null) { + logger.warn("Exceeded JMSException threshold, closing consumer"); + sourceCounter.incrementEventReadFail(); + consumer.rollback(); + consumer.close(); + consumer = null; } } catch (Throwable throwable) { logger.error("Unexpected error processing events", throwable);
flume-ng-sources/flume-jms-source/src/test/java/org/apache/flume/source/jms/TestIntegrationActiveMQ.java+1 −0 modified@@ -90,6 +90,7 @@ private enum TestMode { private final String jmsPassword; public TestIntegrationActiveMQ(TestMode testMode) { + System.setProperty(JMSSource.JNDI_ALLOWED_PROTOCOLS, "tcp"); LOGGER.info("Testing with test mode {}", testMode); switch (testMode) {
flume-ng-sources/flume-jms-source/src/test/java/org/apache/flume/source/jms/TestJMSSource.java+1 −0 modified@@ -64,6 +64,7 @@ public class TestJMSSource extends JMSMessageConsumerTestBase { @SuppressWarnings("unchecked") @Override void afterSetup() throws Exception { + System.setProperty(JMSSource.JNDI_ALLOWED_PROTOCOLS, "dummy"); baseDir = Files.createTempDir(); passwordFile = new File(baseDir, "password"); Assert.assertTrue(passwordFile.createNewFile());
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
6- github.com/advisories/GHSA-9w4g-fp9h-3q2vghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2022-42468ghsaADVISORY
- github.com/apache/flume/commit/eee179a09df405c1ab55ae25a53b76ca1050bb97ghsaWEB
- issues.apache.org/jira/browse/FLUME-3437ghsaWEB
- lists.apache.org/thread/1ckhmp539zr2nd2rs45pocpywk2d9zvzghsaWEB
- lists.apache.org/thread/939wkx8o90bp6m2ht3t1sdyo1ncypl78ghsaWEB
News mentions
0No linked articles in our index yet.