Skip to content

Restricts ZookeeperDistributedQueue deserialization to an allowlist (CWE-502) - #133

Open
Colhodm wants to merge 8 commits into
develop-7.0.xfrom
devin/1792621929-zk-queue-deserialization-allowlist
Open

Colhodm wants to merge 8 commits into
develop-7.0.xfrom
devin/1792621929-zk-queue-deserialization-allowlist

Conversation

@Colhodm

@Colhodm Colhodm commented Oct 21, 2026 •

Copy link
Copy Markdown

A Brief Overview
ZookeeperDistributedQueue.deserialize() called ObjectInputStream.readObject() on bytes read from ZooKeeper with no class filtering. Anyone who can write to the queue znodes could plant a gadget chain and get RCE in every node that polls the queue (CWE-502, Critical).

What changed (core/broadleaf-framework/.../util/queue/ZookeeperDistributedQueue.java)

  • deserialize() now installs a per-stream ObjectInputFilter: exact allowlisted class names, ending in !*. The allowlist covers JDK value/collection types (including List.of immutable collections and java.time.*), the SolrUpdateCommand types, and SolrDocumentBase/SolrInputDocument/SolrInputField. It also sets maxdepth, maxarray (1,000,000, ZooKeeper's 1MB znode cap), maxrefs and maxbytes. Subclasses can extend the allowlist with overridable hooks.
  • Read path: readQueueInternal() deletes a znode only when the filter actually returned REJECTED, so a poisoned head entry can't block the queue. Blocking take/poll go back to waiting when every scanned entry was discarded. The rejection is caught inside the GenericOperation, so it isn't retried.
  • Write path: writeToQueue() round-trips each entry through deserialize() before writing. Entries the filter rejects throw IllegalArgumentException, null entries throw NullPointerException, and entries that come back null are rejected (a polled null looks like an empty queue). The exact validated bytes are re-serialized and written. A bulk addAll is validated up front, so one bad entry rejects the whole batch, but payloads are not held in memory.
  • maxCapacity config is written and read with a final, paired encoder/decoder behind an Integer-only filter. The legacy custom-format fallback to deserialize() only runs for bytes that are not a Java serialization stream.

Additional context

  • New ZookeeperDistributedQueueDeserializationTest (24 tests) plus an org.example.gadget.Gadget test class that sits outside the allowlist. Local run: mvn -B -q -pl core/broadleaf-framework -am test -Dtest=ZookeeperDistributedQueueDeserializationTest → Tests run: 24, Failures: 0, Errors: 0, Skipped: 0. The InvalidClassException: filter status: REJECTED stack traces in the log are the expected rejections being logged.
  • The repo has no CI, so this PR shows 0 checks.
  • This duplicates the earlier fix in Restrict ZookeeperDistributedQueue deserialization with an ObjectInputFilter allowlist (CWE-502) #132 (same commits, cherry-picked onto a fresh branch from develop-7.0.x). Only one of the two should land.

Devin-Org: engineering

Link to Devin session: https://devin-gtm.devinenterprise.com/sessions/e1959b30293d487bb73c2011e4de60a3
Open in Devin Desktop: https://devin-gtm.devinenterprise.com/desktop/session/e1959b30293d487bb73c2011e4de60a3?variant=devin
Requested by: @Colhodm


Devin Review

Status Commit
⚪ Not started —

Run Devin Review

💡 Connect your GitHub account to enable automatic code reviews.

Devin Review (Staging)


Devin Review

devin-ai-integration Bot and others added 8 commits October 21, 2026 22:32
…tInputFilter allowlist (CWE-502)

Co-Authored-By: Arjun Mishra <arjunsaxmishra@gmail.com>
…and cap array length

Co-Authored-By: Arjun Mishra <arjunsaxmishra@gmail.com>
…so report serialClass)

Co-Authored-By: Arjun Mishra <arjunsaxmishra@gmail.com>
…ytes, don't retain bulk payloads

Co-Authored-By: Arjun Mishra <arjunsaxmishra@gmail.com>
…city config with a fixed filter

Co-Authored-By: Arjun Mishra <arjunsaxmishra@gmail.com>
…decoder, fall back for legacy custom-format config

Co-Authored-By: Arjun Mishra <arjunsaxmishra@gmail.com>
… never pass Java-stream config to the deserialize override

Co-Authored-By: Arjun Mishra <arjunsaxmishra@gmail.com>
…to null before writing

Co-Authored-By: Arjun Mishra <arjunsaxmishra@gmail.com>
@devin-ai-integration

Copy link
Copy Markdown

I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".

  • Disable automatic comment, CI, and merge conflict monitoring

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant