CVE-2026-59286
This Vulnerability has been fixed in the Never-Ending Support (NES) version offered by HeroDevs.
Overview
Spring for GraphQL is the GraphQL project in the Spring portfolio. It builds on GraphQL Java and wires a GraphQL engine into Spring MVC, WebFlux, RSocket and WebSocket transports, adding annotated controller handler methods, data loaders, schema inspection and testing support. It also ships a ready to use GraphiQL browser page so developers can explore a running schema without adding a UI of their own.
An Insufficient Verification of Data Authenticity vulnerability (CVE-2026-59286) has been identified in the stock GraphiQL page bundled with Spring for GraphQL, which allows attackers to execute arbitrary JavaScript in the origin of the affected application by substituting the third-party scripts and stylesheets that the page loads from a public CDN without any integrity metadata.
Per CWE: The product downloads source code or an executable from a remote location and executes the code without sufficiently verifying the origin and integrity of the code.
This issue affects the bundled GraphiQL UI page of Spring for GraphQL.
Details
Module Info
- Product: Spring for GraphQL
- Affected packages:
org.springframework.graphql:spring-graphql - Affected versions: >=1.0.0 <=1.0.7, >=1.1.0 <=1.3.9, >=1.4.0 <=1.4.6, >=2.0.0 <=2.0.4
- 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: nes-v1.0.18, nes-v1.2.16, nes-v1.3.12, and nes-v1.4.8
- OSS Spring for GraphQL: 2.0.5
Vulnerability Info
This High-severity vulnerability is found in the org.springframework.graphql:spring-graphql package in the GraphiQL UI support of Spring for GraphQL.
The library ships a stock GraphiQL page as a classpath resource, and applications that enable the GraphiQL endpoint serve that page directly to browsers. The page never bundles the GraphiQL assets it needs. Instead it pulls its stylesheets and ES modules straight from a public CDN, and every one of those references is declared with no Subresource Integrity metadata, so the browser executes whatever bytes the CDN returns:
<link rel="stylesheet" href="https://esm.sh/graphiql@5.0.0/dist/style.css"/>
<link rel="stylesheet" href="https://esm.sh/@graphiql/plugin-explorer@5.0.0/dist/style.css"/>
<script type="importmap">
{
"imports": {
"react": "https://esm.sh/react@19.1.0",
"react-dom": "https://esm.sh/react-dom@19.1.0",
"graphiql": "https://esm.sh/graphiql@5.0.0?standalone&external=react,react-dom,@graphiql/react,graphql",
"@graphiql/plugin-explorer": "https://esm.sh/@graphiql/plugin-explorer@5.0.0?standalone&external=react,@graphiql/react,graphql",
"@graphiql/react": "https://esm.sh/@graphiql/react@0.35.0?standalone&external=react,react-dom,graphql",
"@graphiql/toolkit": "https://esm.sh/@graphiql/toolkit@0.11.3?standalone&external=graphql",
"graphql": "https://esm.sh/graphql@16.11.0"
}
}
</script>
Older lines load the same UI from a different CDN, and several of those URLs are not even pinned to a version, which makes the delivered code free to change at any time and impossible to cover with an integrity hash:
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<link rel="stylesheet" href="https://unpkg.com/graphiql/graphiql.min.css" />
...
<script src="https://unpkg.com/graphiql/graphiql.min.js" type="application/javascript"></script>
An attacker who can influence what those requests return, through a compromised or malicious CDN account, a hijacked package on the CDN, or any position on the network path such as a proxy or a poisoned DNS answer, controls script that the browser then runs with the full privileges of the application origin. Because the page is served from the application itself, that script reads and writes same-origin storage and cookies that are not marked HttpOnly, reaches the application's own GraphQL endpoint with the user's session, and can rewrite the page the developer is looking at. Releases from 1.2.3 onward also seed the page's request headers from the XSRF-TOKEN cookie, so the substituted code inherits the value needed to pass CSRF checks:
const xsrfToken = document.cookie.match(new RegExp('(?:^| )XSRF-TOKEN=([^;]+)'));
const initialHeaders = xsrfToken ? `{ "X-XSRF-TOKEN" : "${ xsrfToken[1] }" }` : `{}`;
The GraphiQL page is intended as a development aid, but it is enabled through a single property and is frequently left switched on in deployed environments, where it is reachable by anyone who can reach the GraphQL endpoint. Exploitation does not require any application flaw, any credentials, or any interaction beyond a user opening the GraphiQL page.
Mitigation
Only recent versions of Spring for GraphQL receive community support. Older lines are End-of-Life and will not receive public updates to address this issue.
Users of the affected components should apply one of the following mitigations:
- Upgrade to a currently supported version of Spring for GraphQL.
- Disable the bundled GraphiQL endpoint in deployed environments by setting
spring.graphql.graphiql.enabledto false, or replace the stock page with a self-hosted copy whose assets are served from the application origin or pinned with Subresource Integrity metadata. - Leverage a commercial support partner like HeroDevs for post-EOL security support.
Credits
- No finder is named in the vendor advisory for this issue.