CVE-2026-41862: Kryo deserialization of persisted context without class allowlist

HIGH | JUNE 11, 2026 | CVE-2026-41862

Description

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.

Affected Spring Products and Versions

Spring Statemachine:

  • 4.0.0 - 4.0.1
  • 3.2.0 - 3.2.4

Mitigation

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.

Register 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.

JPA:

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

MongoDB:

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

Redis:

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

ZooKeeper:

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.

Wire-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.

Redis 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));

Credit

This issue was discovered internally.

References

History

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

Get ahead

VMware offers training and certification to turbo-charge your progress.

Learn more

Get support

Tanzu Spring offers support and binaries for OpenJDK™, Spring, and Apache Tomcat® in one simple subscription.

Learn more

Upcoming events

Check out all the upcoming events in the Spring community.

View all