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 5f0f50a0d277666726d3a79f4eb19ccded2895f2
Author: Andor Molnar <[email protected]>
AuthorDate: Thu Jul 9 12:27:13 2026 -0500

    Missing ACL check in setWatches() on reconnect
---
 .../java/org/apache/zookeeper/server/DataTree.java | 22 +++++++++++++++++-----
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git 
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/DataTree.java 
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/DataTree.java
index 81789d642..265c44e41 100644
--- a/zookeeper-server/src/main/java/org/apache/zookeeper/server/DataTree.java
+++ b/zookeeper-server/src/main/java/org/apache/zookeeper/server/DataTree.java
@@ -1523,9 +1523,9 @@ public void setWatches(long relativeZxid, List<String> 
dataWatches, List<String>
             DataNode node = getNode(path);
             WatchedEvent e = null;
             if (node == null) {
-                watcher.process(new WatchedEvent(EventType.NodeDeleted, 
KeeperState.SyncConnected, path));
+                processWatchEvent(watcher, new 
WatchedEvent(EventType.NodeDeleted, KeeperState.SyncConnected, path), null);
             } else if (node.stat.getMzxid() > relativeZxid) {
-                watcher.process(new WatchedEvent(EventType.NodeDataChanged, 
KeeperState.SyncConnected, path));
+                processWatchEvent(watcher, new 
WatchedEvent(EventType.NodeDataChanged, KeeperState.SyncConnected, path), new 
ArrayList<>(getACL(node)));
             } else {
                 this.dataWatches.addWatch(path, watcher);
             }
@@ -1533,7 +1533,7 @@ public void setWatches(long relativeZxid, List<String> 
dataWatches, List<String>
         for (String path : existWatches) {
             DataNode node = getNode(path);
             if (node != null) {
-                watcher.process(new WatchedEvent(EventType.NodeCreated, 
KeeperState.SyncConnected, path));
+                processWatchEvent(watcher, new 
WatchedEvent(EventType.NodeCreated, KeeperState.SyncConnected, path), new 
ArrayList<>(getACL(node)));
             } else {
                 this.dataWatches.addWatch(path, watcher);
             }
@@ -1541,9 +1541,9 @@ public void setWatches(long relativeZxid, List<String> 
dataWatches, List<String>
         for (String path : childWatches) {
             DataNode node = getNode(path);
             if (node == null) {
-                watcher.process(new WatchedEvent(EventType.NodeDeleted, 
KeeperState.SyncConnected, path));
+                processWatchEvent(watcher, new 
WatchedEvent(EventType.NodeDeleted, KeeperState.SyncConnected, path), null);
             } else if (node.stat.getPzxid() > relativeZxid) {
-                watcher.process(new 
WatchedEvent(EventType.NodeChildrenChanged, KeeperState.SyncConnected, path));
+                processWatchEvent(watcher, new 
WatchedEvent(EventType.NodeChildrenChanged, KeeperState.SyncConnected, path), 
new ArrayList<>(getACL(node)));
             } else {
                 this.childWatches.addWatch(path, watcher);
             }
@@ -1558,6 +1558,18 @@ public void setWatches(long relativeZxid, List<String> 
dataWatches, List<String>
         }
     }
 
+    /**
+     * Route replayed events through the ACL-aware overload so they get the 
same
+     * READ check as WatchManager.triggerWatch; acl is null for a deleted node.
+     */
+    private void processWatchEvent(Watcher watcher, WatchedEvent event, 
List<ACL> acl) {
+        if (watcher instanceof ServerWatcher) {
+            ((ServerWatcher) watcher).process(event, acl);
+        } else {
+            watcher.process(event);
+        }
+    }
+
     /**
      * This method sets the Cversion and Pzxid for the specified node to the
      * values passed as arguments. The values are modified only if newCversion

Reply via email to