fix: don't resolve a wire-supplied manifest class the serializer will not use - #3495
Open
pjfanning wants to merge 1 commit into
Open
fix: don't resolve a wire-supplied manifest class the serializer will not use#3495pjfanning wants to merge 1 commit into
pjfanning wants to merge 1 commit into
Conversation
… not use Motivation: Serialization.deserializeByteArray resolved the manifest string from the wire into a Class via dynamicAccess.getClassFor for every plain Serializer, without checking whether that serializer wants a type hint. Serializers.manifestFor shows a conforming peer only sends a manifest when includeManifest is true, so for a serializer declaring includeManifest = false the class name can only have come from a non-conforming or hostile sender - and the loaded class is then discarded. ByteArraySerializer and NullSerializer are bound by default and reachable by serializer id, so a peer could name any class on the classpath and have it loaded: a classpath-probing oracle, and metaspace and manifest-cache growth that is never released. Modification: Pass None to a plain Serializer that declares includeManifest = false instead of resolving the wire-supplied name, which is exactly what a conforming sender produces. Serializers that do ask for the hint are unchanged. Result: A peer can no longer drive class loading through a serializer that ignores the type hint. No behaviour change for conforming messages. Tests: - sbt "actor-tests/testOnly org.apache.pekko.serialization.WireManifestClassLoadingSpec" - new; the first case fails without this change with "Cannot find manifest class [com.example.NotOnTheClasspath]" - sbt "actor-tests/testOnly org.apache.pekko.serialization.SerializeSpec" - existing spec passes unchanged - sbt "actor/mimaReportBinaryIssues" - no issues References: Refs apache#3478
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.
Motivation
Serialization.deserializeByteArrayresolves the manifest string carried on the wire into aClassviadynamicAccess.getClassForfor every plainSerializerwith a non-empty manifest — without checking whether that serializer actually wants a type hint.Serializers.manifestForis the sending side:So a conforming peer never sends a manifest to a serializer declaring
includeManifest = false. When one arrives anyway it can only have come from a non-conforming or hostile sender — and the class that gets loaded is then handed to a serializer that ignores it.ByteArraySerializerandNullSerializerboth declareincludeManifest = falseand are bound by default, reachable by serializer id from the wire. A peer can therefore name any class on the classpath and have it loaded. The class is loaded withClass.forName(fqcn, false, loader)so static initializers do not run, but it still gives:NotSerializableExceptionfingerprints which libraries and versions are present;manifestCache, for each distinct class an attacker names.Modification
Pass
Noneto a plainSerializerthat declaresincludeManifest = false, instead of resolving the wire-supplied name — exactly what a conforming sender produces for that serializer. Serializers that do ask for the hint (e.g.ProtobufSerializer) are unchanged.One-line guard, no new configuration, no API change.
Result
A peer can no longer drive class loading through a serializer that ignores the type hint. Conforming messages behave exactly as before.
Tests
sbt "actor-tests/testOnly org.apache.pekko.serialization.WireManifestClassLoadingSpec"— new. The first case is directional: with the fix reverted it fails withjava.io.NotSerializableException: Cannot find manifest class [com.example.NotOnTheClasspath] for serializer with id [9911], which is the wire-driven load this change removes. The other two cases pin unchanged behaviour forincludeManifest = true, including that an unknown manifest class still fails.sbt "actor-tests/testOnly org.apache.pekko.serialization.SerializeSpec"— existing spec passes unchangedsbt "actor/mimaReportBinaryIssues"— no issuesReferences
Refs #3478