Harden Redis cache codec (DotObjectCodec) against unsafe Java deserialization
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 970
- Forks
- 486
- Avg merge
- 3d 33m
- Merged PRs (30d)
- 170
Description
Description
DotObjectCodec (dotCMS/src/main/java/com/dotcms/cache/lettuce/DotObjectCodec.java) serializes and deserializes every object stored in a Redis-backed cache region using plain Java ObjectOutputStream / ObjectInputStream (wrapped with GZIP by MasterReplicaLettuceClient). Native Java deserialization is a well-known remote-code-execution surface: an actor who can write arbitrary bytes into the Redis instance backing the cache could deliver a crafted serialized payload (e.g. a ysoserial-style gadget chain) that executes during readObject() on the dotCMS side.
This is an infrastructure trust-boundary concern, not something reachable from ordinary end-user input — exploitation requires write access to the shared Redis used as a cache provider. It is therefore lower urgency than a directly user-facing vulnerability. However, because Redis is often a shared or managed service, defense-in-depth is warranted.
Context: This was surfaced while fixing #34435 (Portlet cache NullPointerException under the Redis provider). That issue is a distinct transient-field bug and is being fixed separately. This issue tracks only the deserialization-codec hardening.
Relevant files:
| File | Concern |
|---|---|
dotCMS/src/main/java/com/dotcms/cache/lettuce/DotObjectCodec.java |
Builds the ObjectInputStream (decodeValue) with no deserialization allow-list |
dotCMS/src/main/java/com/dotcms/cache/lettuce/MasterReplicaLettuceClient.java |
Wires DotObjectCodec + GZIP as the default codec for all Redis-cached objects |
dotCMS/src/main/java/com/dotcms/cache/lettuce/RedisCache.java |
get() / extractObject() — deserialization entry point; failures currently logged at debug only |
Acceptance Criteria
- To be refined — quick draft; details to be added later.
- Apply a JDK
ObjectInputFilter(JEP 290) allow-list to theObjectInputStreaminDotObjectCodec, restricting deserialization to the set of dotCMS-cacheable types plus safe JDK collection/wrapper classes. - Payloads that fail the filter are rejected (treated as a cache miss) and logged at
warn/error— never atdebugonly. - Evaluate whether a safer serialization format (or per-region codec) is feasible for cache payloads.
dotCMS Version
Current Evergreen 26.07.13-1
Priority
Medium
Additional Context
- Native Java deserialization gadget chains are a standard RCE vector; the standard mitigation is a JEP 290
ObjectInputFilterallow-list rather than unrestrictedreadObject(). - Related: #34435 (Portlet cache NPE under Redis — the
transient initParamsfix; separate PR). - The diagnostics gap noted in #34435 research applies here too:
RedisCache.get()swallows deserialization exceptions atdebuglevel, so a malformed/rejected payload is currently near-invisible in logs.
Links
Freshdesk ticket of the related issue: https://helpdesk.dotcms.com/a/tickets/34992
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with dotCMS/src/main/java/com/dotcms/cache/lettuce/DotObjectCodec.java, especially decodeValue and its ObjectInputStream construction. Trace the codec and GZIP wiring in MasterReplicaLettuceClient.java, then follow RedisCache.java get()/extractObject() to understand failure handling. Done means rejected payloads are filtered and logged above debug, the cache behavior is covered, and safer serialization or per-region codec feasibility is assessed.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, redis
- Domain
- backend, infrastructure, security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100