Add an optional JEP-290 ObjectInputFilter to JdkSerializer - #12862
Open
Nexory wants to merge 2 commits into
Open
Add an optional JEP-290 ObjectInputFilter to JdkSerializer#12862Nexory wants to merge 2 commits into
Nexory wants to merge 2 commits into
Conversation
JdkSerializer.deserialize reads Java-serialized bytes back from a process-external store (it is the default cache and session value serializer used by micronaut-redis) and previously installed no java.io.ObjectInputFilter, so any class on the classpath could be deserialized from that input. Add an opt-in filter, configurable via a new JdkSerializer(ConversionService, ObjectInputFilter) constructor and an optional micronaut.serializer.jdk.serial-filter system property, and apply it in createObjectInput. The default is unchanged (no filter) so existing deployments are unaffected. resolveClass is left untouched.
Contributor
There was a problem hiding this comment.
Pull request overview
This PR adds an opt-in JEP-290 ObjectInputFilter integration to Micronaut’s JdkSerializer deserialization path, allowing deployments (e.g., Redis-backed cache/session storage) to restrict which classes may be deserialized from untrusted external stores.
Changes:
- Added an optional
ObjectInputFiltertoJdkSerializer, including a system-property-based default (micronaut.serializer.jdk.serial-filter). - Applied the filter to
ObjectInputStreaminstances created duringdeserialize(...). - Added Spock tests covering both rejection and acceptance cases when using a filter.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| core/src/main/java/io/micronaut/core/serialize/JdkSerializer.java | Adds optional ObjectInputFilter support (constructor + system property) and applies the filter during object input stream creation. |
| core/src/test/groovy/io/micronaut/core/serialize/JdkSerializerSpec.groovy | Adds tests validating that disallowed classes are rejected and allowed classes still round-trip under the filter. |
- Wrap the IllegalArgumentException from ObjectInputFilter.Config.createFilter so a misconfigured micronaut.serializer.jdk.serial-filter names the property and the offending value. - Fix the createObjectInput javadoc return type (ObjectInputStream).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #12861
What / Why
JdkSerializeris Micronaut's defaultObjectSerializer(ObjectSerializer.JDK) and the default value serializer used bymicronaut-redisfor cache and HTTP session storage, so itsdeserialize(...)path reads Java-serialized bytes back from a process-external store (Redis, and other cache/session backends). TodaycreateObjectInput(...)overrides onlyresolveClass(...)for classloader resolution and installs nojava.io.ObjectInputFilter(JEP-290), so any class on the classpath is deserialized from that untrusted input. Installing a JEP-290ObjectInputFilteron this path is the standard mitigation for this class of deserialization exposure.This PR adds an optional, opt-in
ObjectInputFiltertoJdkSerializer:JdkSerializer(ConversionService, ObjectInputFilter)to install a scoped filter programmatically.micronaut.serializer.jdk.serial-filter, taking a standardObjectInputFilter.Config.createFilter(String)pattern, so a deployment can enable filtering on this path without subclassingObjectInputStream.createObjectInput(...).resolveClass(...)is left unchanged.Non-breaking
The default is unchanged. With no property set and no filter argument the filter is
nulland behaviour is byte-for-byte identical to before. Existing callers, including the sharedObjectSerializer.JDKinstance, are unaffected.Tests
JdkSerializerSpecadds two cases: a restrictive filter makes deserialization of a disallowed class fail (surfaced asSerializationException), and a filter that allows the required type still round-trips. The existing round-trip and null cases are unchanged.Notes
Kept intentionally minimal and opt-in so it cannot affect existing deployments. Happy to adjust the surface to whatever the team prefers: default the filter on with a conservative resource-limit pattern (
maxdepth/maxrefs/maxbytes/maxarray), bind it through@ConfigurationPropertiesinstead of a system property, or keep only the constructor and drop the property. Whichever default is chosen, the single choke point stays in one place.