VYPR
Medium severity6.0OSV Advisory· Published Jun 28, 2025· Updated Apr 15, 2026

CVE-2025-53393

CVE-2025-53393

Description

In Akka through 2.10.6, akka-cluster-metrics uses Java serialization for cluster metrics.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
com.typesafe.akka:akka-cluster-metrics_3Maven
<= 2.10.6
com.typesafe.akka:akka-cluster-metrics_2.13Maven
<= 2.10.6

Affected products

1

Patches

1
d69a082abfa2

fix: Don't use Java serialization for cluster metrics (#32748)

https://github.com/akka/akkaPatrik NordwallJun 24, 2025via ghsa
3 files changed · +50 23
  • akka-cluster-metrics/src/main/scala/akka/cluster/metrics/Metric.scala+9 7 modified
    @@ -260,13 +260,15 @@ private[metrics] trait MetricNumericConverter {
        * May involve rounding or truncation.
        */
       def convertNumber(from: Any): Either[Long, Double] = from match {
    -    case n: Int        => Left(n)
    -    case n: Long       => Left(n)
    -    case n: Double     => Right(n)
    -    case n: Float      => Right(n)
    -    case n: BigInt     => Left(n.longValue)
    -    case n: BigDecimal => Right(n.doubleValue)
    -    case x             => throw new IllegalArgumentException(s"Not a number [$x]")
    +    case n: Int                  => Left(n)
    +    case n: Long                 => Left(n)
    +    case n: Double               => Right(n)
    +    case n: Float                => Right(n)
    +    case n: BigInt               => Left(n.longValue)
    +    case n: java.math.BigInteger => Left(n.longValue)
    +    case n: BigDecimal           => Right(n.doubleValue)
    +    case n: java.math.BigDecimal => Right(n.doubleValue)
    +    case x                       => throw new IllegalArgumentException(s"Not a number [$x]")
       }
     
     }
    
  • akka-cluster-metrics/src/main/scala/akka/cluster/metrics/protobuf/MessageSerializer.scala+35 15 modified
    @@ -22,6 +22,8 @@ import akka.serialization.{ BaseSerializer, SerializationExtension, SerializerWi
     import akka.util.ClassLoaderObjectInputStream
     import scala.jdk.CollectionConverters._
     
    +import akka.serialization.DisabledJavaSerializer
    +
     /**
      * Protobuf serializer for [[akka.cluster.metrics.ClusterMetricsMessage]] types.
      */
    @@ -186,23 +188,35 @@ class MessageSerializer(val system: ExtendedActorSystem) extends SerializerWithS
           cm.NodeMetrics.EWMA.newBuilder().setValue(x.value).setAlpha(x.alpha)
         }
     
    -    def numberToProto(number: Number): cm.NodeMetrics.Number.Builder = {
    +    @tailrec def numberToProto(number: Number): cm.NodeMetrics.Number.Builder = {
           import cm.NodeMetrics.Number
           import cm.NodeMetrics.NumberType
           number match {
             case n: jl.Double  => Number.newBuilder().setType(NumberType.Double).setValue64(jl.Double.doubleToLongBits(n))
             case n: jl.Long    => Number.newBuilder().setType(NumberType.Long).setValue64(n)
             case n: jl.Float   => Number.newBuilder().setType(NumberType.Float).setValue32(jl.Float.floatToIntBits(n))
             case n: jl.Integer => Number.newBuilder().setType(NumberType.Integer).setValue32(n)
    +        case n: java.math.BigInteger =>
    +          numberToProto(n.longValue) // this truncation is anyway in MetricNumericConverter
    +        case n: BigInt => numberToProto(n.toLong) // this truncation is anyway in MetricNumericConverter
    +        case n: java.math.BigDecimal =>
    +          numberToProto(n.doubleValue) // this rounding is anyway in MetricNumericConverter
    +        case n: BigDecimal => numberToProto(n.toDouble) // this rounding is anyway in MetricNumericConverter
             case _ =>
    -          val bos = new ByteArrayOutputStream
    -          val out = new ObjectOutputStream(bos)
    -          out.writeObject(number)
    -          out.close()
    -          Number
    -            .newBuilder()
    -            .setType(NumberType.Serialized)
    -            .setSerialized(ByteStringUtils.toProtoByteStringUnsafe(bos.toByteArray))
    +          if (system.settings.AllowJavaSerialization) {
    +            val bos = new ByteArrayOutputStream
    +            val out = new ObjectOutputStream(bos)
    +            out.writeObject(number)
    +            out.close()
    +            Number
    +              .newBuilder()
    +              .setType(NumberType.Serialized)
    +              .setSerialized(ByteStringUtils.toProtoByteStringUnsafe(bos.toByteArray))
    +          } else {
    +            // this is the default, and it shouldn't happen since all number types should be covered above
    +            throw throw new DisabledJavaSerializer.JavaSerializationException(
    +              s"Unsupported number [${number.getClass.getName}], when Java serialization is disabled")
    +          }
           }
         }
     
    @@ -253,12 +267,18 @@ class MessageSerializer(val system: ExtendedActorSystem) extends SerializerWithS
             case NumberType.Float_VALUE   => jl.Float.intBitsToFloat(number.getValue32)
             case NumberType.Integer_VALUE => number.getValue32
             case NumberType.Serialized_VALUE =>
    -          val in = new ClassLoaderObjectInputStream(
    -            system.dynamicAccess.classLoader,
    -            new ByteArrayInputStream(number.getSerialized.toByteArray))
    -          val obj = in.readObject
    -          in.close()
    -          obj.asInstanceOf[jl.Number]
    +          if (system.settings.AllowJavaSerialization) {
    +            val in = new ClassLoaderObjectInputStream(
    +              system.dynamicAccess.classLoader,
    +              new ByteArrayInputStream(number.getSerialized.toByteArray))
    +            val obj = in.readObject
    +            in.close()
    +            obj.asInstanceOf[jl.Number]
    +          } else {
    +            // this is the default, and it shouldn't happen since all number types should be covered above
    +            throw throw new DisabledJavaSerializer.JavaSerializationException(
    +              s"Unsupported number [${number.getClass.getName}], when Java serialization is disabled")
    +          }
           }
         }
     
    
  • akka-cluster-metrics/src/test/scala/akka/cluster/metrics/protobuf/MessageSerializerSpec.scala+6 1 modified
    @@ -4,6 +4,8 @@
     
     package akka.cluster.metrics.protobuf
     
    +import java.math.BigInteger
    +
     import akka.actor.{ Address, ExtendedActorSystem }
     import akka.cluster.MemberStatus
     import akka.cluster.TestMember
    @@ -52,7 +54,10 @@ class MessageSerializerSpec extends AkkaSpec("""
                   Metric("bar2", Float.MaxValue, None),
                   Metric("bar3", Int.MaxValue, None),
                   Metric("bar4", Long.MaxValue, None),
    -              Metric("bar5", BigInt(Long.MaxValue), None)))))
    +              Metric("bar5", BigInt(Long.MaxValue), None),
    +              Metric("bar6", new BigInteger(s"${Long.MaxValue}"), None),
    +              Metric("bar7", BigDecimal.exact(s"${Long.MaxValue}.0"), None),
    +              Metric("bar8", new java.math.BigDecimal(s"${Long.MaxValue}.0"), None)))))
     
           checkSerialization(MetricsGossipEnvelope(a1.address, metricsGossip, true))
     
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

4

News mentions

0

No linked articles in our index yet.