ZooKeeper's ACL checks were bypassed twice, in code paths that rarely get reviewed
ZooKeeper's ACL checks were bypassed twice, in code paths that rarely get reviewed
pache ZooKeeper 3.9.6 and 3.8.7 fix a set of access-control and logging defects published on 16 September 2026. Two of them show authorization checks placed on the common path while an uncommon path around them stayed open.
A delete that never asks for permission
CVE-2026-79993 (CVSS 3.1 base 7.5, CWE-862) concerns the deleteContainer opcode, value 20. The regular delete opcode checks the session and enforces DELETE permission against the node's ACL. The container delete path performs neither check.
The advisory is unusually direct about the consequence: any client that can open a plain TCP session to the client port, 2181 by default, can delete an empty persistent znode regardless of the ACLs on that znode or its parent. Container nodes, TTL nodes and ordinary persistent nodes are all in scope. The opcode is described as internal-only, and the official client exposes no API for it, which is precisely why it received less scrutiny.
Affected versions are 3.9.0 through 3.9.5 and 3.8.0 through 3.8.6.
The precondition is an empty node. A node holding children cannot be removed this way, and the advisory does not claim it can. That narrows the blast radius without making the bug small: coordination metadata, leader-election paths, and configuration nodes are frequently leaf nodes with restrictive ACLs, and their deletion is a denial-of-service event for everything registered against them.
Disclosure through a watch replay
CVE-2026-59739 (7.5, CWE-862) is described by Apache as an incomplete fix for CVE-2024-23944. The earlier work added ACL checking to WatchManager.triggerWatch(). The reconnect handler DataTree.setWatches(), which replays SetWatches and SetWatches2 registrations, still invokes watcher.process(event) with a null ACL and therefore bypasses the check entirely.
The attack sequence in the advisory is simple. Register exists-watches on paths that do not exist yet. Reconnect after the paths are created with restricted ACLs. The replayed watch fires for a path the client should not be able to see.
Apache is careful about impact: only the path is disclosed, not the znode data. It also does not make the bug harmless, because path names in real deployments encode tenant identifiers, usernames, job identifiers and configuration keys, and the advisory says as much.
Why partial fixes are the recurring pattern
Both CVEs share a structure. A control was implemented at the place most traffic passes through, and a second entry point for the same operation was left unguarded.
For ZooKeeper specifically, the shape of the code makes that easy to repeat. The server exposes a binary protocol with many opcodes, some of which no client library will generate. Every opcode that mutates the tree needs the same authorization decision, and the review question is not "does delete check ACLs" but "which tree-mutating requests reach the data tree without an ACL check".
The watch replay case adds a second wrinkle. The watch subsystem has two delivery paths, live notification and reconnect replay, and the earlier fix covered one. Any future change to watch handling should be tested against both.
Verification before and after the upgrade
Version inventory comes first. The deleteContainer issue spans 3.9.0 to 3.9.5 and 3.8.0 to 3.8.6, and the watch replay issue shares the same affected ranges. Both are fixed in 3.9.6 and 3.8.7, so a single upgrade closes them together.
Checking that upgrade is straightforward from a node with network access to the ensemble. echo srvr | nc <host> 2181 returns a Zookeeper version line on the four-letter-word endpoint when that endpoint is enabled. ruok returns imok on a healthy server and says nothing about version, so prefer srvr when you need the number.
That test also raises the operative question for most operators. The four-letter-word interface that makes srvr convenient is an information exposure of its own, and the whitelist controlling it, zookeeper.4lw.commands.whitelist, is usually set to a narrow list in production. A deployment that answers srvr to any host on the network has a separate problem from the one these CVEs describe.
For the ACL bypass, the meaningful verification is a regression test rather than a probe. Against a test ensemble with a node protected by a restrictive ACL, attempt a container delete through a raw protocol client before and after the upgrade. Before, the node is removed; after, the server refuses. Apache's fix for the watch path is covered by the same release and is harder to observe directly, so tracking the version is the practical control.
The monitoring angle nobody patches
ZooKeeper sits under systems that expect an immutable tree. Deleting a leaf node that other clients watch produces cascading failures far from the ZooKeeper host: a scheduler loses its leader key, a service registry loses an entry, a configuration consumer reverts to stale defaults.
None of that appears in ZooKeeper's own logs unless audit logging is enabled, which brings the remaining two CVEs into view. CVE-2026-84439 and CVE-2026-84501, both rated 5.3, allow injected content to reach the audit log and the operational log respectively. Their details deserve separate treatment, but the operational point is simple: an environment where deletion cannot be reconstructed afterwards has a monitoring gap independent of the ACL defects.
Upgrading to 3.9.6 or 3.8.7 fixes the code. Reconstructing who deleted what requires that audit logging was already on, that its output is shipped off the host, and that the parser downstream expects untrusted input.
References
- Apache ZooKeeper advisory for CVE-2026-79993: https://lists.apache.org/thread/9cw3rmrzhqpct26v8j18fy41bghlq8y5
- Openwall mirror for CVE-2026-79993: http://www.openwall.com/lists/oss-security/2026/09/15/5
- Apache ZooKeeper advisory for CVE-2026-59739: https://lists.apache.org/thread/v0lrwsbdxvx6w67p3z7fxf3hzyncq55l
- Apache ZooKeeper 3.9.6 and 3.8.7 release notes: https://zookeeper.apache.org/releases.html
- ZooKeeper administrator's guide, four-letter words: https://zookeeper.apache.org/doc/current/zookeeperAdmin.html
- NVD records: https://nvd.nist.gov/vuln/detail/CVE-2026-79993, https://nvd.nist.gov/vuln/detail/CVE-2026-59739
Did you enjoy this article?
Recommend it — Standard Reader surfaces well-loved writing to more readers across the network.