CVE-2026-41862

Updated on 11 Jun 2026

Severity

7.0 High severity

Details

CVSS score
7.0

Overview

About vulnerability

SVG ImageDescription

Spring Statemachine’s Kryo-based persistence backends (JPA, MongoDB, Redis and ZooKeeper) deserialise persisted state-machine contexts without enforcing a class allowlist (CWE-502, deserialisation of untrusted data), which can lead to remote code execution inside the application JVM.

SVG ImageAffected Spring Products and Versions

Spring Statemachine:

  • 4.0.0 - 4.0.1
  • 3.2.0 - 3.2.4

SVG ImageMitigation

Users of affected versions should upgrade to the corresponding fixed version:

Affected version(s) Fix version Availability
4.0.x 4.0.2 OSS
4.0.x 4.0.1.1 Enterprise Support Only
3.2.x 3.2.5 Enterprise Support Only

The fixed releases enable Kryo.setRegistrationRequired(true) and register an explicit allowlist of framework and JDK types via a new KryoStateMachineSerialisationDefaults helper. This is a behaviour change that affects every application using custom state or event types: those types must now be registered with Kryo explicitly, otherwise Kryo throws IllegalArgumentException: Class is not registered on the first persist / load.

SVG ImageRegister application-specific state and event types

Each persistence-layer factory accepts a new Consumer<Kryo> callback that is invoked once per Kryo instance after the framework defaults are applied. Use it to register your application’s S (state) and E (event) classes.

SVG ImageJPA:

@Bean public StateMachineRuntimePersister<MyStates, MyEvents, String> stateMachineRuntimePersister(JpaStateMachineRepository repo) { return new JpaPersistingStateMachineInterceptor<>(repo, kryo -> { kryo.register(MyStates.class); kryo.register(MyEvents.class); }); }

SVG ImageMongoDB:

@Bean public StateMachineRuntimePersister<MyStates, MyEvents, String> stateMachineRuntimePersister(MongoDbStateMachineRepository repo) { return new MongoDbPersistingStateMachineInterceptor<>(repo, kryo -> { kryo.register(MyStates.class); kryo.register(MyEvents.class); }); }

SVG ImageRedis:

@Bean public StateMachineRuntimePersister<MyStates, MyEvents, String> stateMachineRuntimePersister(RedisStateMachineRepository repo) { return new RedisPersistingStateMachineInterceptor<>(repo, kryo -> { kryo.register(MyStates.class); kryo.register(MyEvents.class); }); }

SVG ImageZooKeeper:

ZookeeperStateMachineEnsemble<MyStates, MyEvents> ensemble = new ZookeeperStateMachineEnsemble<>(curatorClient, “/state”, true, 32, kryo -> { kryo.register(MyStates.class); kryo.register(MyEvents.class); });

If event headers or extended-state variables contain types beyond the JDK and framework defaults already registered by KryoStateMachineSerialisationDefaults, register those types inside the same Consumer<Kryo> as well.

SVG ImageWire-format incompatibility

With registration required, Kryo identifies classes by registered numeric id rather than by class name. State-machine contexts persisted by older releases cannot be read by the fixed version. Drain or migrate the persistence backend during the upgrade, or accept that pre-upgrade contexts are unreadable.

SVG ImageRedis key namespace

RedisStateMachineContextRepository now prepends every Redis key with a fixed namespace (ssm:context: by default) so that user-supplied machine ids cannot collide with unrelated keys in the same logical database. Existing keys written by older releases are not visible after the upgrade; either rewrite contexts under the new namespace or, only if backwards compatibility is required, pass an empty prefix:

new RedisStateMachineContextRepository<>(connectionFactory, “”, kryo -> kryo.register(MyStates.class));

SVG ImageCredit

This issue was discovered internally.

SVG ImageReferences

SVG ImageHistory

  • 2026-06-11: Initial vulnerability report published.

Details

SVG ImageDescription

Spring Statemachine’s Kryo-based persistence backends (JPA, MongoDB, Redis and ZooKeeper) deserialise persisted state-machine contexts without enforcing a class allowlist (CWE-502, deserialisation of untrusted data), which can lead to remote code execution inside the application JVM.

SVG ImageAffected Spring Products and Versions

Spring Statemachine:

  • 4.0.0 - 4.0.1
  • 3.2.0 - 3.2.4

SVG ImageMitigation

Users of affected versions should upgrade to the corresponding fixed version:

Affected version(s) Fix version Availability
4.0.x 4.0.2 OSS
4.0.x 4.0.1.1 Enterprise Support Only
3.2.x 3.2.5 Enterprise Support Only

The fixed releases enable Kryo.setRegistrationRequired(true) and register an explicit allowlist of framework and JDK types via a new KryoStateMachineSerialisationDefaults helper. This is a behaviour change that affects every application using custom state or event types: those types must now be registered with Kryo explicitly, otherwise Kryo throws IllegalArgumentException: Class is not registered on the first persist / load.

SVG ImageRegister application-specific state and event types

Each persistence-layer factory accepts a new Consumer<Kryo> callback that is invoked once per Kryo instance after the framework defaults are applied. Use it to register your application’s S (state) and E (event) classes.

SVG ImageJPA:

@Bean public StateMachineRuntimePersister<MyStates, MyEvents, String> stateMachineRuntimePersister(JpaStateMachineRepository repo) { return new JpaPersistingStateMachineInterceptor<>(repo, kryo -> { kryo.register(MyStates.class); kryo.register(MyEvents.class); }); }

SVG ImageMongoDB:

@Bean public StateMachineRuntimePersister<MyStates, MyEvents, String> stateMachineRuntimePersister(MongoDbStateMachineRepository repo) { return new MongoDbPersistingStateMachineInterceptor<>(repo, kryo -> { kryo.register(MyStates.class); kryo.register(MyEvents.class); }); }

SVG ImageRedis:

@Bean public StateMachineRuntimePersister<MyStates, MyEvents, String> stateMachineRuntimePersister(RedisStateMachineRepository repo) { return new RedisPersistingStateMachineInterceptor<>(repo, kryo -> { kryo.register(MyStates.class); kryo.register(MyEvents.class); }); }

SVG ImageZooKeeper:

ZookeeperStateMachineEnsemble<MyStates, MyEvents> ensemble = new ZookeeperStateMachineEnsemble<>(curatorClient, “/state”, true, 32, kryo -> { kryo.register(MyStates.class); kryo.register(MyEvents.class); });

If event headers or extended-state variables contain types beyond the JDK and framework defaults already registered by KryoStateMachineSerialisationDefaults, register those types inside the same Consumer<Kryo> as well.

SVG ImageWire-format incompatibility

With registration required, Kryo identifies classes by registered numeric id rather than by class name. State-machine contexts persisted by older releases cannot be read by the fixed version. Drain or migrate the persistence backend during the upgrade, or accept that pre-upgrade contexts are unreadable.

SVG ImageRedis key namespace

RedisStateMachineContextRepository now prepends every Redis key with a fixed namespace (ssm:context: by default) so that user-supplied machine ids cannot collide with unrelated keys in the same logical database. Existing keys written by older releases are not visible after the upgrade; either rewrite contexts under the new namespace or, only if backwards compatibility is required, pass an empty prefix:

new RedisStateMachineContextRepository<>(connectionFactory, “”, kryo -> kryo.register(MyStates.class));

SVG ImageCredit

This issue was discovered internally.

SVG ImageReferences

SVG ImageHistory

  • 2026-06-11: Initial vulnerability report published.