Java vulnerabilities of the week: 29 October to 4 November 2026
One of this week’s ZooKeeper advisories comes down to a question every SASL server has to answer: this client proved it is one principal, may it act as the one it asked for? The 8.6 score gives you nothing to look for in your own code; the question does. That is the point of this series, the mechanism you can carry into a code review, and the longer argument is in the CVE stigma post.
This is 29 October to 4 November 2026, and it is mostly Apache: ZooKeeper, Wicket, ActiveMQ and Syncope published more than thirty CVEs between them. MariaDB Connector/J starts three days before the window, and its dated where it comes up.
The theme is revocation. In ZooKeeper a request authorized just before an ACL change could commit just after it, in ActiveMQ a connection kept its write access through a live ACL update, and in Wicket a WebSocket connection outlived the session it was opened with. The deep dives are the ZooKeeper SASL bug, a code one, and the Wicket batch, a design story about one enforcement point and the routes around it.
The week in five
-
Apache ZooKeeper, five CVEs disclosed 3 November, fixed in 3.8.8 and 3.9.7. In
CVE-2026-100252(Important, 8.6) a SASL client whose principal falls outside theauth_to_localrules could take any identity it named, the superuser included (first deep dive).CVE-2026-100235(Moderate) is asetACLrace: a request prepared during the change was checked against the old ACL and applied after the new one, so a client could keep writing, or grant itself permissions again, through its own revocation. An unauthenticated client on a default deployment can leave the server unable to restart, with malformed data under the world-writable/zookeeper/quota(CVE-2026-100300) or a znode chain deep enough to overflow the recursive snapshot serializer (CVE-2026-115448), and a smallmultiReadcan build a response far bigger then the request (CVE-2026-100302). The snapshot advisory’s header lists 3.8.8 and 3.9.7 as affected while its text names them as the fix; both release tags contain it. -
Apache Wicket, 19 CVEs disclosed 1 November, fixed in 8.20.0, 9.25.0 and 10.12.0. Most fall into two families: authorization that did not run on every route to a protected object (second deep dive), and escaping for the wrong context.
JavaScriptUtils#escapeQuotes()did not escape the backslash, so\'became\\'and the quote closed the string literal (CVE-2026-83559).ExternalLinkon a non-anchor tag put its URL into anonclickstring with HTML escaping only, which the browser decodes before it runs the handler (CVE-2026-84231, 8.x only). AndAuthenticatedWebSession#signIn()renewed the session id only on the first sign-in, a session fixation on re-authentication (CVE-2026-82840). 8.20.0 and 9.25.0 are the last releases of their lines. -
Apache ActiveMQ, five broker CVEs disclosed 3 November, fixed in 5.19.12, 6.3.3 and 6.4.0. The broker took connection ids from the client without always checking they belong to the sending connection (
CVE-2026-108946, Important): with a victim’s connection id in its ownConsumerId, a client could read the victim’s temporary queue, drop its subscription or acknowledge away a message in flight. A connection kept writing after the runtime configuration plugin removed its grant, because the security context caches writable destinations (CVE-2026-111822, Important). And a Java detail: KahaDB indexes durable subscriptions byclientId + ":" + subscriptionNameand writes keys withDataOutput.writeUTF, whose length prefix is 16 bits, so two strings each under the limit make a key the store cannot write, and per the advisory the broker shuts down and does not recover (CVE-2026-111821). The other two are LDAP DN injection and a heap leak. -
Apache Syncope, five CVEs disclosed 2 November, fixed in 4.0.9 and 4.1.4. Administrator-supplied Groovy runs behind a sandbox whose interceptor lived in a
ThreadLocal, so code that started a newThreadran unchecked (CVE-2026-113687, Important); the test that ships with the fix calls"whoami".execute()from inside one. The fix moves togroovy-security-sandbox1.1.0, which registers the interceptor in anyRunnablehanded tonew Thread()or anExecutor. InCVE-2026-109083(Moderate) Flowable evaluated JUEL from a BPMN definition an administrator imported, with no sandbox, and the fix rejects definitions with expression attributes. The rest are two privilege escalations and stacked SQL through the audit search, a follow-up toCVE-2026-77051. The 3.0 line, affected through 3.0.16, has no fixed release. -
MariaDB Connector/J, seven advisories published on GitHub on 26 October (CVE records 29 October), fixed in 3.3.7, 3.4.5, 3.5.11 and 4.0.0. All assume a malicious or impersonated server. In
CVE-2026-119210(Medium) the driver answers a server’s LOCAL INFILE request by sending the file, after checking that its own query was aLOAD DATA LOCAL INFILEof that file. The check was a regular expression whose prefix accepts any character, so it asked whether the text appeared anywhere in the SQL. And the driver reuses names the server returns: if the server names its databaseLOAD DATA LOCAL INFILE '/etc/passwd',DatabaseMetaData.getImportedKeys()sends that name back, quoted, in aSHOW CREATE TABLE, the server asks for/etc/passwd, and the check passes.allowLocalInfiledefaults to true. The fix parses the statement instead. Most of the other six are server-declared lengths, such as an 8 MiB field in an 18-byte OK packet.
A few smaller ones. Apache Thrift CVE-2026-120135 (Important, 31 October): before 0.24.0, TProtocolUtil.skip() recursed with a default depth of Integer.MAX_VALUE; 0.24.0, out since July, takes the limit from TConfiguration (64 by default) and turns setMaxSkipDepth() into a no-op. Apache MINA CVE-2026-118636 (9.8, 31 October): JavaNativeMessageDecoder in the 3.0 milestones deserializes with no class filter and will not be fixed, so use 2.2.x. Apache Juneau 9.2.1 (3 November) fixes nine issues. On 30 October the reporter of the PLC4X OPC UA CVEs from 30 September explained them: verify() threw on a valid signature (a missing negation) and was handed the pre-decryption length, so together a forged signature passed, and fixing the negation alone would reject legitimate responses. Only 1.0.0 is fixed, and Camel moves to it in 4.24.0 (CAMEL-25617). And on 30 October Oracle added products that embed Java, Oracle Database Server among them, to the eMudhra alert from last week’s post.
ZooKeeper: the identity a client asks for is not the one it proved
SASL keeps two identities apart on purpose: the authentication ID the client proved, a Kerberos principal with GSSAPI, and the authorization ID (authzid) it wants to act as, which exists so a gateway can act for a user. A Java server decides in its CallbackHandler, which gets an AuthorizeCallback holding both strings and answers with setAuthorized(boolean), optionally naming a canonical identity with setAuthorizedID(). In the JDK’s GSSAPI server the authzid is whatever the client put in its last token, and the callback resolves the result like this:
public String getAuthorizedID() {
if (!authorized) {
return null;
}
return (authorizedID == null) ? authorizationID : authorizedID;
}
So if the handler says yes and names no identity, the session gets the identity the client asked for. ZooKeeper adds it as new Id("sasl", authorizationID), plus super when it matches zookeeper.superUser.
The client port handler called ac.setAuthorized(true) first, then canonicalized the authentication ID with KerberosName.getShortName() and passed the result to setAuthorizedID(). For a principal in the default realm that overwrites the requested authzid, and the session gets the proved identity. For any other realm, under the default auth_to_local rule, getShortName() throws NoMatchingRule; the handler logged the IOException and returned, still authorized and with no authorized ID. A client authenticated as bob@CROSSREALM (the case in the fix’s own test) that asks for the superuser name gets the whole tree.
The fix, commit 0afc927, compares the two IDs first and denies on a mismatch, the same authenticationID.equals(authorizationID) check the quorum port’s SaslQuorumServerCallbackHandler makes.
Why I find it interesting
It is improper authorization, CWE-285, in the form where the identity used for access control is not the one that was authenticated. Each line reads correctly on its own, authorize, canonicalize, log the failure; the bug is the order plus a JDK default, and in the common same-realm setup it never shows.
Two habits follow. Write a security decision last, after everything that can throw, with deny as the default. And treat a SASL principal as two strings: if you maintain a SASL server in Java, grep for AuthorizeCallback and check what happens when they differ. Without proxy users the rule is equality; with them it is an explicit list of who may act as whom.
Wicket: an enforcement point covers only the routes that pass through it
Wicket’s IAuthorizationStrategy holds an application’s access rules and answers three questions: may this class be instantiated, may this component RENDER or ENABLE, and may this resource be served. The rules live in one place and the framework asks at the right moment. Most of this batch is about the moments.
The resource question is asked in one place, the constructor of ResourceRequestHandler, built for requests to a mounted or shared ResourceReference. But ResourceLink, Image, ImageButton and AjaxDownloadBehavior can also be handed an IResource, and then they served it themselves:
Attributes a = new Attributes(RequestCycle.get().getRequest(), RequestCycle.get()
.getResponse(), null);
resource.respond(a);
So the constructor decided whether the check ran: new ResourceLink(id, reference) was authorized and new ResourceLink(id, resource) was not. ExportToolbar uses the second form (CVE-2026-82705). The WebSocket transport called onPayload() on a shared WebSocketResource directly, so @AuthorizeResource had no effect there (CVE-2026-82115).
RENDER had its own way around. The outcome of the RENDER check is stored in a visibility flag that only Component#configure() writes, during rendering. A bookmarkable listener URL with an empty page id makes Wicket build a fresh page and invoke the listener before any render pass, so the flag still says visible and a denied component’s listener runs (CVE-2026-82704). For stateless pages Wicket writes such URLs itself.
The fixes make each route ask the strategy. ResourceLink.onRequest() now responds through new ResourceRequestHandler(resource, resourceParameters), which in the commit’s words “keeps one enforcement point rather than adding a second one that can drift”; the WebSocket transport asks about the resource a client connects to; and a fresh page gets its RENDER check before the listener runs.
Why I find it interesting
This is missing authorization, CWE-862, measured against complete mediation, every access to every object checked, as Saltzer and Schroeder put it in 1975. A single enforcement point is the right way to get there, and the fix kept it rather then adding checks to each component. The review question is which routes reach the object without passing through the check. Thats a question about entry points, here a second constructor, a second transport and a request that skipped a lifecycle phase, and it fits any Java stack: a filter on /admin/* does not see the same handler reached through a WebSocket, a message listener or a scheduled job.
The RENDER case adds that a decision stored as state is only as current as the code that last wrote it, which is the revocation theme one level down. Fifteen of the nineteen advisories credit Emond Papegaaij, who sent the announcement for the PMC.
What I take away from this week
First, revocation. ZooKeeper’s prepared request, ActiveMQ’s per-connection write cache and Wicket’s session copy from the handshake each held a permission longer than the policy did. When code keeps an authorization decision on a long-lived object, find the event that should invalidate it and test it: revoke, then try the old connection. Its the cheapest test I know for all three.
Second, identity taken from a field the client fills in: the ZooKeeper authzid, the connection id in an ActiveMQ ConsumerId, the upload limits Wicket read from request parameters (CVE-2026-84170). In each case the server already knew the answer from its own state, and the fix uses that.
Third, where the fixes land. ZooKeeper, ActiveMQ, Wicket, Syncope and Juneau are direct upgrades, and all five ActiveMQ items are in the broker. Camel main has moved to ZooKeeper 3.9.7, PLC4X 1.0.0 and MariaDB Connector/J 4.0.0 for 4.24.0. MariaDB is the one to act on now: Spring Boot 4.0.9 and 4.1.2 and Quarkus 3.40.1 manage 3.5.10, so override it to 3.5.11 (mariadb.version in Spring Boot) until the next patch releases. If you don’t use LOAD DATA LOCAL INFILE, allowLocalInfile=false also works, since 3.5.9 enforces it for server-initiated requests (CVE-2026-61700, July). Thrift users on 0.24.0 or later, Camel included, already have that fix. Every fixed version named here is on Maven Central; I checked.
References
- oss-security: Apache ZooKeeper SASL authorization bypass CVE-2026-100252 - Openwall oss-security
- oss-security: Apache ZooKeeper setACL race CVE-2026-100235 - Openwall oss-security
- oss-security: Apache ZooKeeper quota denial of service CVE-2026-100300 - Openwall oss-security
- oss-security: Apache ZooKeeper multiRead allocation CVE-2026-100302 - Openwall oss-security
- oss-security: Apache ZooKeeper snapshot recursion CVE-2026-115448 - Openwall oss-security
- ZooKeeper fix: SASL authzid validation on the client port - apache/zookeeper on GitHub
- AuthorizeCallback.java - openjdk/jdk on GitHub
- GssKrb5Server.java - openjdk/jdk on GitHub
- oss-security: Apache Wicket: 19 CVEs fixed in 8.20.0, 9.25.0 and 10.12.0 - Openwall oss-security
- Apache Wicket CVE-2026-82705: authorization strategy not applied to an IResource embedded in a component - Apache mailing lists
- Apache Wicket CVE-2026-82115: authorization strategy not applied to a shared WebSocketResource - Apache mailing lists
- Apache Wicket CVE-2026-82704: listener invoked on a page instance never configured - Apache mailing lists
- Apache Wicket CVE-2026-82559: WebSocket messages processed against an HTTP session snapshot - Apache mailing lists
- Apache Wicket CVE-2026-83559: escapeQuotes does not escape the backslash - Apache mailing lists
- Apache Wicket CVE-2026-84231: XSS in ExternalLink on a non-anchor tag - Apache mailing lists
- Wicket fix: ask IAuthorizationStrategy about a resource served by a component - apache/wicket on GitHub
- Wicket fix: re-evaluate the RENDER authorization on a freshly created page - apache/wicket on GitHub
- Wicket fix: ask IAuthorizationStrategy about the WebSocketResource a client connects to - apache/wicket on GitHub
- oss-security: Apache ActiveMQ connection id validation CVE-2026-108946 - Openwall oss-security
- oss-security: Apache ActiveMQ write access after live ACL revocation CVE-2026-111822 - Openwall oss-security
- oss-security: Apache ActiveMQ KahaDB client identifier length CVE-2026-111821 - Openwall oss-security
- oss-security: Apache ActiveMQ LDAPAuthorizationMap DN injection CVE-2026-108500 - Openwall oss-security
- oss-security: Apache ActiveMQ rejected temporary destination subscriptions CVE-2026-108949 - Openwall oss-security
- ActiveMQ fix: validate subscription key length in KahaDB - apache/activemq on GitHub
- oss-security: Apache Syncope Groovy sandbox bypass CVE-2026-113687 - Openwall oss-security
- oss-security: Apache Syncope Flowable JUEL expression CVE-2026-109083 - Openwall oss-security
- oss-security: Apache Syncope audit events SQL injection CVE-2026-114364 - Openwall oss-security
- Syncope fix: strengthen Groovy sandbox - apache/syncope on GitHub
- groovy-security-sandbox issue 2: propagate SandboxInterceptor to child threads - Tirasa on GitHub
- MariaDB Connector/J LOAD DATA LOCAL INFILE advisory GHSA-fhx5-2xqw-2cgm - mariadb-corporation/mariadb-connector-j on GitHub
- MariaDB Connector/J OK packet allocation advisory GHSA-h599-m3w5-9m7x - mariadb-corporation/mariadb-connector-j on GitHub
- oss-security: Apache Thrift TProtocolUtil.skip() recursion depth CVE-2026-120135 - Openwall oss-security
- oss-security: Apache MINA JavaNativeMessageDecoder CVE-2026-118636 - Openwall oss-security
- oss-security: Apache Juneau 9.2.1 fixes multiple vulnerabilities - Openwall oss-security
- oss-security: Apache PLC4X OPC UA mechanisms for CVE-2026-102508 and CVE-2026-102509 - Openwall oss-security
- CAMEL-25617: camel-plc4x, upgrade to PLC4X 1.0 - Apache JIRA
- Oracle Security Alert for CVE-2026-114820 - Oracle
- Java vulnerabilities of the week: 22 to 28 October 2026 - oscerd.github.io
- The CVE stigma, we need a new security culture - oscerd.github.io