Skip to content

fix: mitigate insecure deserialization in ZookeeperDistributedQueue (CWE-502)#17

Open
devin-ai-integration[bot] wants to merge 2 commits intodevelop-7.0.xfrom
devin/1776983572-fix-insecure-deserialization
Open

fix: mitigate insecure deserialization in ZookeeperDistributedQueue (CWE-502)#17
devin-ai-integration[bot] wants to merge 2 commits intodevelop-7.0.xfrom
devin/1776983572-fix-insecure-deserialization

Conversation

@devin-ai-integration
Copy link
Copy Markdown

@devin-ai-integration devin-ai-integration Bot commented Apr 23, 2026

Overview

ZookeeperDistributedQueue.deserialize() used a raw ObjectInputStream.readObject() on data read from Zookeeper with no class filtering. This is a well-known deserialization vulnerability (CWE-502) that can lead to Remote Code Execution if an attacker can influence data stored in Zookeeper nodes.

Labels: Security, critical, ready-for-code-review

Changes

The deserialize() method now uses a filtering ObjectInputStream that overrides resolveClass() to validate each class name against a prefix-based allowlist before permitting deserialization. Classes not matching any allowed prefix are rejected with an InvalidClassException.

The default allowlist (DEFAULT_ALLOWED_DESERIALIZATION_PREFIXES) permits:

  • org.broadleafcommerce.* — all Broadleaf domain types (e.g. SolrUpdateCommand)
  • org.apache.solr.* — Solr types required by IncrementalUpdateCommand (which contains SolrInputDocument fields)
  • java.lang.*, java.math.*, java.util.*, java.time.* — standard JDK types (covers Integer used for config storage)

JVM array type descriptors are handled generically in resolveClass():

  • Leading [ markers are stripped to handle multi-dimensional arrays (e.g. [[I)
  • Object type wrappers (L...;) are unwrapped to extract the component class name (e.g. [Ljava.lang.String;java.lang.String)
  • Single-char primitive descriptors (B, C, I, J, S, D, F, Z) are always permitted

The filter is extensible: subclasses can override getAllowedDeserializationPrefixes() to widen or narrow the allowlist. The createFilteredObjectInputStream() factory method is also protected for further customization.

Human review checklist

  1. Allowlist breadth: org.broadleafcommerce. and org.apache.solr. are broad prefixes. A narrower scope (e.g. org.broadleafcommerce.core.search.service.solr.indexer.) would be more restrictive but risks breaking extensibility. Worth a judgement call.
  2. No unit tests: This PR does not add tests for the filtering behavior. Consider whether test coverage for allowed/rejected class deserialization is needed before merge.
  3. Array unwrapping correctness: Verify the resolveClass logic handles all JVM type descriptor edge cases correctly — particularly nested object arrays like [[[Ljava.util.List;.

Link to Devin session: https://app.devin.ai/sessions/7573a5bd991a427aacde1f410f0903af
Requested by: @Colhodm


Open in Devin Review

…CWE-502)

Replace unfiltered ObjectInputStream.readObject() with a filtering
ObjectInputStream that validates class names against an allowlist
before deserialization. This prevents Remote Code Execution (RCE)
via crafted payloads stored in Zookeeper.

The allowlist permits only Broadleaf Commerce classes, standard Java
types (java.lang, java.util, java.math, java.time), and primitive
arrays. Subclasses can override getAllowedDeserializationPrefixes()
to customize the allowlist.

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 and CI monitoring

devin-ai-integration[bot]

This comment was marked as resolved.

…n deserialization filter

Address Devin Review findings:
- Add org.apache.solr. to the allowlist since IncrementalUpdateCommand
  contains SolrInputDocument fields from that package.
- Unwrap JVM array type descriptors (e.g. [Ljava.lang.String;) to their
  component class name before checking against allowed prefixes.
- Remove now-unnecessary explicit primitive array prefixes since primitive
  type descriptors are handled by the single-char check after stripping.

Co-Authored-By: Arjun Mishra <arjunsaxmishra@gmail.com>
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