CVE-2026-41699
This Vulnerability has been fixed in the Never-Ending Support (NES) version offered by HeroDevs.
Overview
Spring for GraphQL is the official Spring project for building GraphQL APIs on top of Spring applications, providing server transports, data fetching integration with Spring Data, and pagination support based on the GraphQL Cursor Connections specification. A high-severity vulnerability (CVE-2026-41699) has been identified in Spring for GraphQL, where applications that expose a paginated (Connection) field can be vulnerable to unsafe deserialization when processing pagination cursors from GraphQL requests. If the application classpath contains classes that execute unintended logic during instantiation or deserialization, an attacker can craft a malicious GraphQL request that leads to remote code execution.
Per OWASP, deserialization of untrusted data occurs when an application deserializes data it does not control. Untrusted data cannot be trusted to be well formed, and malformed or unexpected data can be used to abuse application logic, deny service, or execute arbitrary code when deserialized.
This issue affects >=1.2.0 <=1.2.9, >=1.3.0 <=1.3.8, >=1.4.0 <=1.4.5, and >=2.0.0 <=2.0.3 of Spring for GraphQL.
Details
Module Info
- Product: Spring for GraphQL
- Affected packages: spring-graphql
- Affected versions: >=1.2.0 <=1.2.9, >=1.3.0 <=1.3.8, >=1.4.0 <=1.4.5, >=2.0.0 <=2.0.3
- GitHub repository: https://github.com/spring-projects/spring-graphql
- Published packages: https://central.sonatype.com/artifact/org.springframework.graphql/spring-graphql
- Package manager: Maven
- Fixed in:
- NES for Spring for GraphQL 1.2.x, 1.3.x
- Spring for GraphQL 2.0.4, 1.4.6 (OSS)
Vulnerability Info
Spring for GraphQL supports paginated queries through Connection types, where each page of results is bounded by opaque cursor strings that clients pass back in the after or before arguments of subsequent requests. When the application uses keyset based scrolling with Spring Data, the JsonKeysetCursorStrategy class serializes the keyset of a scroll position to JSON to produce the cursor, and deserializes the client supplied cursor string back into a Map of keys.
To preserve the concrete Java types of the keyset values across that round trip, the strategy configures its Jackson ObjectMapper with default typing, so the cursor JSON embeds the fully qualified class name to instantiate, for example:
K_["java.util.Collections$UnmodifiableMap",{"firstName":"Joseph","lastName":"Heller","id":103}]The PolymorphicTypeValidator that is supposed to restrict which classes may be instantiated was configured too broadly:
PolymorphicTypeValidator validator = BasicPolymorphicTypeValidator.builder()
.allowIfBaseType(Map.class)
.allowIfSubType("java.time.")
.allowIfSubType(Calendar.class)
.allowIfSubType(Date.class)
.build();
ObjectMapper mapper = Jackson2ObjectMapperBuilder.json().build();
mapper.activateDefaultTyping(validator, ObjectMapper.DefaultTyping.NON_FINAL);
The allowIfBaseType(Map.class) rule allows any class assignable to java.util.Map to be named in the cursor and instantiated by Jackson. Because the cursor string is fully attacker controlled, an attacker can name any Map implementation present on the application classpath. If such a class executes logic during construction or deserialization, a so-called gadget class, sending a crafted cursor in a paginated GraphQL query can trigger that logic and lead to remote code execution. The fix replaces the broad base type rule with a strict allowlist of common map implementations such as LinkedHashMap and HashMap, so cursors that name any other type are rejected with an IllegalArgumentException.
This vulnerability was introduced in 2023 with Spring for GraphQL 1.2.
Mitigation
Spring for GraphQL 1.2.x and 1.3.x are past their open source support period and have no publicly available fix for this vulnerability. For more information about Spring for GraphQL support timelines, see https://spring.io/projects/spring-graphql#support.
We recommend one of the following actions:
- Upgrade to Spring for GraphQL 2.0.4 or 1.4.6, which contain the fix.
- If you need to stay on the 1.2.x or 1.3.x release lines, use a commercial support partner like HeroDevs. Never-Ending Support (NES) for Spring for GraphQL includes a fix for this vulnerability.