Skip to content

Restrict ZookeeperDistributedQueue deserialization to an allow-list (CWE-502)#49

Open
devin-ai-integration[bot] wants to merge 1 commit into
develop-7.0.xfrom
devin/1782340488-zk-queue-deserialization-filter
Open

Restrict ZookeeperDistributedQueue deserialization to an allow-list (CWE-502)#49
devin-ai-integration[bot] wants to merge 1 commit into
develop-7.0.xfrom
devin/1782340488-zk-queue-deserialization-filter

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Jun 24, 2026

Copy link
Copy Markdown

Add proper title
Restricting ZookeeperDistributedQueue deserialization to an allow-list to prevent insecure deserialization / RCE (CWE-502).

A Brief Overview
ZookeeperDistributedQueue.deserialize() called ObjectInputStream.readObject() on bytes read from Zookeeper with no class filtering. If an attacker can influence the data stored in Zookeeper, a crafted serialized payload could instantiate arbitrary classes during read and reach a gadget chain, leading to remote code execution.

The fix installs a JDK-native JEP 290 ObjectInputFilter (no new dependency) on the ObjectInputStream before readObject(). The filter is an allow-list limited to the types this queue actually carries, plus resource limits to bound work per entry:

maxbytes=10485760;maxdepth=100;maxrefs=100000;maxarray=100000;
java.**;javax.**;org.apache.solr.common.**;org.broadleafcommerce.**;!*

!* rejects every other class (primitives stay allowed). The queue stores Broadleaf SolrUpdateCommand subtypes carrying org.apache.solr.common.SolrInputDocument/SolrInputField plus JDK collections, and an Integer for the max-capacity config — all covered by the allow-list.

Pseudo-diff of the hot path:

 ois = new ObjectInputStream(bais);
+ois.setObjectInputFilter(getDeserializationFilter()); // allow-list, rejects unexpected classes
 return ois.readObject();

The filter is exposed via a new protected ObjectInputFilter getDeserializationFilter() and the DESERIALIZATION_ALLOW_LIST constant so subclasses that place additional types on the queue can extend it rather than disable filtering. serialize() is unchanged.

Add Labels to the right panel and delete this list:

  • Security
  • Severity: critical
  • Status: ready-for-code-review

Additional context
Added ZookeeperDistributedQueueDeserializationTest (run name matches the repo's documented single-test command) verifying that:

  • an Integer config value and an IncrementalUpdateCommand (with a SolrInputDocument) round-trip successfully, and
  • a serializable type outside the allow-list is rejected with an InvalidClassException cause (wrapped as DistributedQueueException).

Local run: mvn -pl core/broadleaf-framework -am test -Dtest=ZookeeperDistributedQueueDeserializationTest → Tests run: 3, Failures: 0, Errors: 0.

Link to Devin session: https://app.devin.ai/sessions/56cbb12633f4438ea09183d46eedf812


Devin Review

Status Commit
⚪ Not started

Run Devin Review

Open in Devin Review (Staging)

… (CWE-502)

Apply a JEP 290 ObjectInputFilter allow-list in ZookeeperDistributedQueue.deserialize()
so untrusted bytes read from Zookeeper can no longer instantiate arbitrary classes (RCE/CWE-502).

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

Copy link
Copy Markdown
Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • 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.

0 participants