Apache Cassandra: Privilege escalation when enabling FQL/Audit logs
Description
Privilege escalation when enabling FQL/Audit logs allows user with JMX access to run arbitrary commands as the user running Apache Cassandra This issue affects Apache Cassandra: from 4.0.0 through 4.0.9, from 4.1.0 through 4.1.1.
WORKAROUND The vulnerability requires nodetool/JMX access to be exploitable, disable access for any non-trusted users.
MITIGATION Upgrade to 4.0.10 or 4.1.2 and leave the new FQL/Auditlog configuration property allow_nodetool_archive_command as false.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Privilege escalation in Apache Cassandra allows users with JMX access to execute arbitrary commands when FQL/Audit logs are enabled.
Vulnerability
Overview
CVE-2023-30601 is a privilege escalation vulnerability in Apache Cassandra that affects versions 4.0.0 through 4.0.9 and 4.1.0 through 4.1.1. The issue arises when the Full Query Logging (FQL) or Audit Logging feature is enabled. A user with JMX (Java Management Extensions) access can exploit this flaw to run arbitrary commands as the user running Apache Cassandra [1].
Exploitation
Details
To exploit this vulnerability, an attacker must have network access to the JMX port (typically 7199) and valid credentials to authenticate to the JMX service. The vulnerability is triggered by sending a crafted command through JMX that causes the database to execute an arbitrary command during the audit log archival process. No additional privileges beyond JMX access are required to execute the exploit [1] [2].
Impact
Successful exploitation allows an attacker with JMX access to execute arbitrary operating system commands with the same privileges as the Apache Cassandra process. This could lead to full compromise of the database server, including data exfiltration, modification, or destruction, as well as lateral movement within the network [1] [2].
Mitigation
Apache has released versions 4.0.10 and 4.1.2, which include a configuration property allow_nodetool_archive_command (defaulting to false) that prevents this exploitation. Users are strongly advised to upgrade to these patched versions. As a workaround, administrators should disable JMX access for any non-trusted users or restrict network access to the JMX port [1] [2].
AI Insight generated on May 20, 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.cassandra:cassandra-allMaven | >= 4.1.0, < 4.1.2 | 4.1.2 |
org.apache.cassandra:cassandra-allMaven | >= 4.0.0, < 4.0.10 | 4.0.10 |
Affected products
4- osv-coords3 versions
< 1.0.80-r0+ 2 more
- (no CPE)range: < 1.0.80-r0
- (no CPE)range: >= 4.0.0, < 4.0.10
- (no CPE)range: >= 4.1.0, < 4.1.2
- Apache Software Foundation/Apache Cassandrav5Range: 4.0.0
Patches
222d74c711658Merge branch 'cassandra-4.0' into cassandra-4.1
1 file changed · +2 −0
test/unit/org/apache/cassandra/fql/FullQueryLoggerTest.java+2 −0 modified@@ -680,6 +680,7 @@ public void testJMXArchiveCommand() try { + DatabaseDescriptor.getFullQueryLogOptions().allow_nodetool_archive_command = false; StorageService.instance.enableFullQueryLogger(options.log_dir, options.roll_cycle, false, 1000, 1000, "/xyz/not/null", 0); fail("not allowed"); } @@ -688,6 +689,7 @@ public void testJMXArchiveCommand() assertTrue(e.getMessage().contains("Can't enable full query log archiving via nodetool")); } + options.allow_nodetool_archive_command = true; options.archive_command = "/xyz/not/null"; options.log_dir = "/tmp/abc"; DatabaseDescriptor.setFullQueryLogOptions(options);
aafb4d19448fImprove nodetool enable{audit,fullquery}log
7 files changed · +46 −2
CHANGES.txt+1 −0 modified@@ -1,4 +1,5 @@ 4.0.10 + * Improve nodetool enable{audit,fullquery}log (CASSANDRA-18550) * Report network cache info in nodetool (CASSANDRa-18400) * Partial compaction can resurrect deleted data (CASSANDRA-18507) * Allow internal address to change with reconnecting snitches (CASSANDRA-16718)
conf/cassandra.yaml+2 −0 modified@@ -1360,6 +1360,8 @@ audit_logging_options: # max_log_size: 17179869184 # 16 GiB ## archive command is "/path/to/script.sh %path" where %path is replaced with the file being rolled: # archive_command: + ## note that enabling this allows anyone with JMX/nodetool access to run local shell commands as the user running cassandra + # allow_nodetool_archive_command: false # max_archive_retries: 10 # validate tombstones on reads and compaction
src/java/org/apache/cassandra/config/DatabaseDescriptor.java+5 −0 modified@@ -3140,6 +3140,11 @@ public static FullQueryLoggerOptions getFullQueryLogOptions() return conf.full_query_logging_options; } + public static void setFullQueryLogOptions(FullQueryLoggerOptions options) + { + conf.full_query_logging_options = options; + } + public static boolean getBlockForPeersInRemoteDatacenters() { return conf.block_for_peers_in_remote_dcs;
src/java/org/apache/cassandra/service/StorageService.java+2 −0 modified@@ -6081,6 +6081,8 @@ public void enableFullQueryLogger(String path, String rollCycle, Boolean blockin blocking = blocking != null ? blocking : fqlOptions.block; maxQueueWeight = maxQueueWeight != Integer.MIN_VALUE ? maxQueueWeight : fqlOptions.max_queue_weight; maxLogSize = maxLogSize != Long.MIN_VALUE ? maxLogSize : fqlOptions.max_log_size; + if (archiveCommand != null && !fqlOptions.allow_nodetool_archive_command) + throw new ConfigurationException("Can't enable full query log archiving via nodetool unless full_query_logging_options.allow_nodetool_archive_command is set to true"); archiveCommand = archiveCommand != null ? archiveCommand : fqlOptions.archive_command; maxArchiveRetries = maxArchiveRetries != Integer.MIN_VALUE ? maxArchiveRetries : fqlOptions.max_archive_retries;
src/java/org/apache/cassandra/tools/nodetool/EnableFullQueryLog.java+2 −1 modified@@ -42,7 +42,8 @@ public class EnableFullQueryLog extends NodeToolCmd private String path = null; @Option(title = "archive_command", name = {"--archive-command"}, description = "Command that will handle archiving rolled full query log files." + - " Format is \"/path/to/script.sh %path\" where %path will be replaced with the file to archive") + " Format is \"/path/to/script.sh %path\" where %path will be replaced with the file to archive" + + " Enable this by setting the full_query_logging_options.allow_nodetool_archive_command: true in the config.") private String archiveCommand = null; @Option(title = "archive_retries", name = {"--max-archive-retries"}, description = "Max number of archive retries.")
src/java/org/apache/cassandra/utils/binlog/BinLogOptions.java+7 −0 modified@@ -23,6 +23,13 @@ public class BinLogOptions { public String archive_command = StringUtils.EMPTY; + + /** + * enable if a user should be able to set the archive command via nodetool/jmx + * + * do not make this a hotprop. + */ + public boolean allow_nodetool_archive_command = false; /** * How often to roll BinLog segments so they can potentially be reclaimed. Available options are: * MINUTELY, HOURLY, DAILY, LARGE_DAILY, XLARGE_DAILY, HUGE_DAILY.
test/unit/org/apache/cassandra/fql/FullQueryLoggerTest.java+27 −1 modified@@ -32,7 +32,6 @@ import org.apache.commons.lang3.StringUtils; import org.junit.After; -import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; @@ -44,15 +43,18 @@ import net.openhft.chronicle.wire.ValueIn; import net.openhft.chronicle.wire.WireOut; import org.apache.cassandra.Util; +import org.apache.cassandra.config.DatabaseDescriptor; import org.apache.cassandra.cql3.CQLTester; import org.apache.cassandra.cql3.QueryOptions; import org.apache.cassandra.cql3.statements.BatchStatement; +import org.apache.cassandra.exceptions.ConfigurationException; import org.apache.cassandra.fql.FullQueryLogger.Query; import org.apache.cassandra.fql.FullQueryLogger.Batch; import org.apache.cassandra.cql3.statements.BatchStatement.Type; import org.apache.cassandra.io.util.FileUtils; import org.apache.cassandra.service.ClientState; import org.apache.cassandra.service.QueryState; +import org.apache.cassandra.service.StorageService; import org.apache.cassandra.transport.ProtocolVersion; import org.apache.cassandra.utils.ObjectSizes; import org.apache.cassandra.utils.binlog.BinLogTest; @@ -74,6 +76,7 @@ import static org.apache.cassandra.fql.FullQueryLogger.TYPE; import static org.apache.cassandra.fql.FullQueryLogger.VALUES; import static org.apache.cassandra.fql.FullQueryLogger.VERSION; +import static org.junit.Assert.fail; public class FullQueryLoggerTest extends CQLTester { @@ -670,6 +673,29 @@ public void testLogQueryNegativeTime() throws Exception logQuery("", QueryOptions.DEFAULT, queryState(), -1); } + @Test + public void testJMXArchiveCommand() + { + FullQueryLoggerOptions options = new FullQueryLoggerOptions(); + + try + { + StorageService.instance.enableFullQueryLogger(options.log_dir, options.roll_cycle, false, 1000, 1000, "/xyz/not/null", 0); + fail("not allowed"); + } + catch (ConfigurationException e) + { + assertTrue(e.getMessage().contains("Can't enable full query log archiving via nodetool")); + } + + options.archive_command = "/xyz/not/null"; + options.log_dir = "/tmp/abc"; + DatabaseDescriptor.setFullQueryLogOptions(options); + StorageService.instance.enableFullQueryLogger(options.log_dir, options.roll_cycle, false, 1000, 1000, null, 0); + assertTrue(FullQueryLogger.instance.isEnabled()); + assertEquals("/xyz/not/null", FullQueryLogger.instance.getFullQueryLoggerOptions().archive_command); + } + private static void compareQueryOptions(QueryOptions a, QueryOptions b) { assertEquals(a.getClass(), b.getClass());
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-m9p2-j4hg-g373ghsaADVISORY
- lists.apache.org/thread/f74p9jdhmmp7vtrqd8lgm8bq3dhxl8vnghsavendor-advisoryWEB
- nvd.nist.gov/vuln/detail/CVE-2023-30601ghsaADVISORY
- github.com/apache/cassandra/commit/22d74c711658507addfd67e2c78b04a9b88413b2ghsaWEB
- github.com/apache/cassandra/commit/aafb4d19448f12ce600dc4e84a5b181308825b32ghsaWEB
- issues.apache.org/jira/browse/CASSANDRA-18550ghsaWEB
News mentions
0No linked articles in our index yet.