This is an automated email from the ASF dual-hosted git repository. anmolnar pushed a commit to branch branch-3.8 in repository https://gitbox.apache.org/repos/asf/zookeeper.git
commit 0cd1cd023cff5e0b3b5a19050e544196ac2340b4 Author: Andor Molnar <[email protected]> AuthorDate: Tue Aug 25 16:18:14 2026 -0500 Missing ACL check on deleteContainer opcode --- .../apache/zookeeper/server/ZooKeeperServer.java | 10 ++++++ .../zookeeper/server/CreateContainerTest.java | 39 ++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/server/ZooKeeperServer.java b/zookeeper-server/src/main/java/org/apache/zookeeper/server/ZooKeeperServer.java index d017d295a..f1cc6752c 100644 --- a/zookeeper-server/src/main/java/org/apache/zookeeper/server/ZooKeeperServer.java +++ b/zookeeper-server/src/main/java/org/apache/zookeeper/server/ZooKeeperServer.java @@ -1680,6 +1680,16 @@ public void processPacket(ServerCnxn cnxn, ByteBuffer incomingBuffer) throws IOE // Already sent response to user about failure and closed the session, lets return return; } else { + // Internal opcodes should not be submitted via client connections + if (h.getType() == OpCode.deleteContainer) { + LOG.warn("Received deleteContainer opcode from client session 0x{}, rejecting.", + Long.toHexString(cnxn.getSessionId())); + // close connection + cnxn.sendBuffer(ServerCnxnFactory.closeConn); + cnxn.disableRecv(); + return; + } + Request si = new Request(cnxn, cnxn.getSessionId(), h.getXid(), h.getType(), incomingBuffer, cnxn.getAuthInfo()); int length = incomingBuffer.limit(); if (isLargeRequest(length)) { diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/server/CreateContainerTest.java b/zookeeper-server/src/test/java/org/apache/zookeeper/server/CreateContainerTest.java index 6722473f2..0229581c7 100644 --- a/zookeeper-server/src/test/java/org/apache/zookeeper/server/CreateContainerTest.java +++ b/zookeeper-server/src/test/java/org/apache/zookeeper/server/CreateContainerTest.java @@ -23,6 +23,8 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; +import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -35,13 +37,19 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; +import org.apache.jute.InputArchive; +import org.apache.jute.OutputArchive; +import org.apache.jute.Record; import org.apache.zookeeper.AsyncCallback; import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.Op; +import org.apache.zookeeper.TestableZooKeeper; import org.apache.zookeeper.ZooDefs; import org.apache.zookeeper.ZooKeeper; import org.apache.zookeeper.data.Stat; +import org.apache.zookeeper.proto.ReplyHeader; +import org.apache.zookeeper.proto.RequestHeader; import org.apache.zookeeper.test.ClientBase; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -339,4 +347,35 @@ private void validateCreateStat(Stat stat, String name) { assertEquals(0, stat.getNumChildren()); } + @Test + @Timeout(value = 30) + public void testDeleteContainerShouldBeRejected() throws Exception { + zk.create("/some", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); + zk.create("/some/child", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); + + TestableZooKeeper zk = createClient(); + + RequestHeader h = new RequestHeader(); + h.setType(ZooDefs.OpCode.deleteContainer); + Record request = new Record() { + private String path = "/some/child"; + + @Override + public void serialize(OutputArchive archive, String tag) throws IOException { + archive.writeBuffer(path.getBytes(StandardCharsets.UTF_8), "path"); + } + + @Override + public void deserialize(InputArchive archive, String tag) throws IOException { + byte[] bytes = archive.readBuffer("path"); + path = new String(bytes, StandardCharsets.UTF_8); + } + }; + ReplyHeader reply = zk.submitRequest(h, request, null, null); + assertEquals(KeeperException.Code.CONNECTIONLOSS.intValue(), reply.getErr(), + "deleteContainer opcode should be rejected from client connections"); + + zk.close(); + } + }
