CVE-2018-1270
Description
Spring Framework STOMP over WebSocket endpoints in spring-messaging allow remote code execution via crafted messages.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Spring Framework STOMP over WebSocket endpoints in spring-messaging allow remote code execution via crafted messages.
Vulnerability
CVE-2018-1270 affects Spring Framework versions 5.0 prior to 5.0.5 and 4.3 prior to 4.3.15, as well as older unsupported versions. The vulnerability resides in the spring-messaging module when applications expose STOMP over WebSocket endpoints with a simple, in-memory STOMP broker. The DefaultSubscriptionRegistry class inappropriately used a StandardEvaluationContext for SpEL expression evaluation, which could lead to arbitrary code execution [1] [2] [3].
Exploitation
An attacker must have network access to the STOMP endpoint and the ability to send a crafted STOMP message. The attack involves sending a specially crafted subscription selector header containing a SpEL expression that is evaluated by the DefaultSubscriptionRegistry without proper sandboxing. The attacker does not require authentication if the endpoint is exposed publicly [1] [2] [3].
Impact
Successful exploitation allows an attacker to achieve remote code execution (RCE) on the server hosting the vulnerable Spring application. The attacker gains the ability to execute arbitrary commands in the context of the application, potentially leading to full compromise of the affected system [1] [4].
Mitigation
Spring Framework released fixed versions 5.0.5 and 4.3.15 to address the vulnerability. The fix involved replacing the StandardEvaluationContext with a SimpleEvaluationContext in the DefaultSubscriptionRegistry, which restricts SpEL evaluation to safe operations [2] [3]. Red Hat also released an advisory (RHSA-2018:2939) for Red Hat FIS 2.0 on Fuse 6.3.0 addressing this and related vulnerabilities [4]. Users should upgrade to the patched versions immediately.
AI Insight generated on May 22, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
org.springframework:spring-messagingMaven | >= 5.0.0.RELEASE, < 5.0.5.RELEASE | 5.0.5.RELEASE |
org.springframework:spring-messagingMaven | < 4.3.16.RELEASE | 4.3.16.RELEASE |
Affected products
2- Spring by Pivotal/Spring Frameworkv5Range: Versions prior to 5.0.5 and 4.3.15
Patches
20009806debb5Re-use EvaluationContext in DefaultSubscriptionRegistry
1 file changed · +27 −19
spring-messaging/src/main/java/org/springframework/messaging/simp/broker/DefaultSubscriptionRegistry.java+27 −19 modified@@ -26,15 +26,14 @@ import java.util.concurrent.ConcurrentMap; import java.util.concurrent.CopyOnWriteArraySet; -import org.springframework.expression.AccessException; import org.springframework.expression.EvaluationContext; import org.springframework.expression.Expression; import org.springframework.expression.ExpressionParser; import org.springframework.expression.PropertyAccessor; import org.springframework.expression.TypedValue; import org.springframework.expression.spel.SpelEvaluationException; import org.springframework.expression.spel.standard.SpelExpressionParser; -import org.springframework.expression.spel.support.StandardEvaluationContext; +import org.springframework.expression.spel.support.SimpleEvaluationContext; import org.springframework.messaging.Message; import org.springframework.messaging.MessageHeaders; import org.springframework.messaging.simp.SimpMessageHeaderAccessor; @@ -64,6 +63,10 @@ public class DefaultSubscriptionRegistry extends AbstractSubscriptionRegistry { /** Default maximum number of entries for the destination cache: 1024 */ public static final int DEFAULT_CACHE_LIMIT = 1024; + /** Static evaluation context to reuse */ + private static EvaluationContext messageEvalContext = + SimpleEvaluationContext.forPropertyAccessors(new SimpMessageHeaderPropertyAccessor()).build(); + private PathMatcher pathMatcher = new AntPathMatcher(); @@ -191,7 +194,6 @@ private MultiValueMap<String, String> filterSubscriptions( if (!this.selectorHeaderInUse) { return allMatches; } - EvaluationContext context = null; MultiValueMap<String, String> result = new LinkedMultiValueMap<String, String>(allMatches.size()); for (String sessionId : allMatches.keySet()) { for (String subId : allMatches.get(sessionId)) { @@ -208,12 +210,8 @@ private MultiValueMap<String, String> filterSubscriptions( result.add(sessionId, subId); continue; } - if (context == null) { - context = new StandardEvaluationContext(message); - context.getPropertyAccessors().add(new SimpMessageHeaderPropertyAccessor()); - } try { - if (expression.getValue(context, boolean.class)) { + if (Boolean.TRUE.equals(expression.getValue(messageEvalContext, message, Boolean.class))) { result.add(sessionId, subId); } } @@ -525,7 +523,7 @@ private static class SimpMessageHeaderPropertyAccessor implements PropertyAccess @Override public Class<?>[] getSpecificTargetClasses() { - return new Class<?>[] {MessageHeaders.class}; + return new Class<?>[] {Message.class, MessageHeaders.class}; } @Override @@ -534,19 +532,29 @@ public boolean canRead(EvaluationContext context, Object target, String name) { } @Override - public TypedValue read(EvaluationContext context, Object target, String name) throws AccessException { - MessageHeaders headers = (MessageHeaders) target; - SimpMessageHeaderAccessor accessor = - MessageHeaderAccessor.getAccessor(headers, SimpMessageHeaderAccessor.class); + public TypedValue read(EvaluationContext context, Object target, String name) { Object value; - if ("destination".equalsIgnoreCase(name)) { - value = accessor.getDestination(); + if (target instanceof Message) { + value = name.equals("headers") ? ((Message) target).getHeaders() : null; } - else { - value = accessor.getFirstNativeHeader(name); - if (value == null) { - value = headers.get(name); + else if (target instanceof MessageHeaders) { + MessageHeaders headers = (MessageHeaders) target; + SimpMessageHeaderAccessor accessor = + MessageHeaderAccessor.getAccessor(headers, SimpMessageHeaderAccessor.class); + Assert.state(accessor != null, "No SimpMessageHeaderAccessor"); + if ("destination".equalsIgnoreCase(name)) { + value = accessor.getDestination(); } + else { + value = accessor.getFirstNativeHeader(name); + if (value == null) { + value = headers.get(name); + } + } + } + else { + // Should never happen... + throw new IllegalStateException("Expected Message or MessageHeaders."); } return new TypedValue(value); }
e0de9126ed8cRe-use EvaluationContext in DefaultSubscriptionRegistry
1 file changed · +29 −22
spring-messaging/src/main/java/org/springframework/messaging/simp/broker/DefaultSubscriptionRegistry.java+29 −22 modified@@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2018 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,15 +26,14 @@ import java.util.concurrent.ConcurrentMap; import java.util.concurrent.CopyOnWriteArraySet; -import org.springframework.expression.AccessException; import org.springframework.expression.EvaluationContext; import org.springframework.expression.Expression; import org.springframework.expression.ExpressionParser; import org.springframework.expression.PropertyAccessor; import org.springframework.expression.TypedValue; import org.springframework.expression.spel.SpelEvaluationException; import org.springframework.expression.spel.standard.SpelExpressionParser; -import org.springframework.expression.spel.support.StandardEvaluationContext; +import org.springframework.expression.spel.support.SimpleEvaluationContext; import org.springframework.lang.Nullable; import org.springframework.messaging.Message; import org.springframework.messaging.MessageHeaders; @@ -65,6 +64,11 @@ public class DefaultSubscriptionRegistry extends AbstractSubscriptionRegistry { /** Default maximum number of entries for the destination cache: 1024 */ public static final int DEFAULT_CACHE_LIMIT = 1024; + /** Static evaluation context to re-use */ + private static SimpleEvaluationContext evaluationContext = SimpleEvaluationContext.builder() + .propertyAccessor(new SimpMessageHeaderPropertyAccessor()).build(); + + private PathMatcher pathMatcher = new AntPathMatcher(); @@ -192,7 +196,6 @@ private MultiValueMap<String, String> filterSubscriptions( if (!this.selectorHeaderInUse) { return allMatches; } - EvaluationContext context = null; MultiValueMap<String, String> result = new LinkedMultiValueMap<>(allMatches.size()); for (String sessionId : allMatches.keySet()) { for (String subId : allMatches.get(sessionId)) { @@ -209,12 +212,8 @@ private MultiValueMap<String, String> filterSubscriptions( result.add(sessionId, subId); continue; } - if (context == null) { - context = new StandardEvaluationContext(message); - context.getPropertyAccessors().add(new SimpMessageHeaderPropertyAccessor()); - } try { - if (Boolean.TRUE.equals(expression.getValue(context, Boolean.class))) { + if (Boolean.TRUE.equals(expression.getValue(evaluationContext, message, Boolean.class))) { result.add(sessionId, subId); } } @@ -533,7 +532,7 @@ private static class SimpMessageHeaderPropertyAccessor implements PropertyAccess @Override public Class<?>[] getSpecificTargetClasses() { - return new Class<?>[] {MessageHeaders.class}; + return new Class<?>[] {Message.class, MessageHeaders.class}; } @Override @@ -542,21 +541,29 @@ public boolean canRead(EvaluationContext context, @Nullable Object target, Strin } @Override - public TypedValue read(EvaluationContext context, @Nullable Object target, String name) throws AccessException { - Assert.state(target instanceof MessageHeaders, "No MessageHeaders"); - MessageHeaders headers = (MessageHeaders) target; - SimpMessageHeaderAccessor accessor = - MessageHeaderAccessor.getAccessor(headers, SimpMessageHeaderAccessor.class); - Assert.state(accessor != null, "No SimpMessageHeaderAccessor"); + public TypedValue read(EvaluationContext context, @Nullable Object target, String name) { Object value; - if ("destination".equalsIgnoreCase(name)) { - value = accessor.getDestination(); + if (target instanceof Message) { + value = name.equals("headers") ? ((Message) target).getHeaders() : null; } - else { - value = accessor.getFirstNativeHeader(name); - if (value == null) { - value = headers.get(name); + else if (target instanceof MessageHeaders) { + MessageHeaders headers = (MessageHeaders) target; + SimpMessageHeaderAccessor accessor = + MessageHeaderAccessor.getAccessor(headers, SimpMessageHeaderAccessor.class); + Assert.state(accessor != null, "No SimpMessageHeaderAccessor"); + if ("destination".equalsIgnoreCase(name)) { + value = accessor.getDestination(); } + else { + value = accessor.getFirstNativeHeader(name); + if (value == null) { + value = headers.get(name); + } + } + } + else { + // Should never happen... + throw new IllegalStateException("Expected Message or MessageHeaders."); } return new TypedValue(value); }
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
27- www.exploit-db.com/exploits/44796/mitreexploitx_refsource_EXPLOIT-DB
- access.redhat.com/errata/RHSA-2018:2939ghsavendor-advisoryx_refsource_REDHATWEB
- github.com/advisories/GHSA-p5hg-3xm3-gcjgghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2018-1270ghsaADVISORY
- www.oracle.com/technetwork/security-advisory/cpujul2018-4258247.htmlghsax_refsource_CONFIRMWEB
- www.oracle.com/technetwork/security-advisory/cpuoct2018-4428296.htmlghsax_refsource_CONFIRMWEB
- www.securityfocus.com/bid/103696mitrevdb-entryx_refsource_BID
- github.com/spring-projects/spring-framework/commit/0009806debb578e884f6dc98bd1f2dc668020021ghsaWEB
- github.com/spring-projects/spring-framework/commit/e0de9126ed8cf25cf141d3e66420da94e350708aghsaWEB
- lists.apache.org/thread.html/4ed49b103f64a0cecb38064f26cbf1389afc12124653da2d35166dbe%40%3Cissues.activemq.apache.org%3Emitremailing-listx_refsource_MLIST
- lists.apache.org/thread.html/4ed49b103f64a0cecb38064f26cbf1389afc12124653da2d35166dbe@%3Cissues.activemq.apache.org%3EghsaWEB
- lists.apache.org/thread.html/6d3d34adcf3dfc48e36342aa1f18ce3c20bb8e4c458a97508d5bfed1%40%3Cissues.activemq.apache.org%3Emitremailing-listx_refsource_MLIST
- lists.apache.org/thread.html/6d3d34adcf3dfc48e36342aa1f18ce3c20bb8e4c458a97508d5bfed1@%3Cissues.activemq.apache.org%3EghsaWEB
- lists.apache.org/thread.html/ab825fcade0b49becfa30235b3d54f4a51bb74ea96b6c9adb5d1378c%40%3Cissues.activemq.apache.org%3Emitremailing-listx_refsource_MLIST
- lists.apache.org/thread.html/ab825fcade0b49becfa30235b3d54f4a51bb74ea96b6c9adb5d1378c@%3Cissues.activemq.apache.org%3EghsaWEB
- lists.apache.org/thread.html/dcf8599b80e43a6b60482607adb76c64672772dc2d9209ae2170f369%40%3Cissues.activemq.apache.org%3Emitremailing-listx_refsource_MLIST
- lists.apache.org/thread.html/dcf8599b80e43a6b60482607adb76c64672772dc2d9209ae2170f369@%3Cissues.activemq.apache.org%3EghsaWEB
- lists.apache.org/thread.html/rf1bbc0ea4a9f014cf94df9a12a6477d24a27f52741dbc87f2fd52ff2%40%3Cissues.geode.apache.org%3Emitremailing-listx_refsource_MLIST
- lists.apache.org/thread.html/rf1bbc0ea4a9f014cf94df9a12a6477d24a27f52741dbc87f2fd52ff2@%3Cissues.geode.apache.org%3EghsaWEB
- lists.debian.org/debian-lts-announce/2021/04/msg00022.htmlghsamailing-listx_refsource_MLISTWEB
- pivotal.io/security/cve-2018-1270ghsax_refsource_CONFIRMWEB
- web.archive.org/web/20200227125035/https://www.securityfocus.com/bid/103696ghsaWEB
- www.exploit-db.com/exploits/44796ghsaWEB
- www.oracle.com/security-alerts/cpujul2020.htmlghsax_refsource_MISCWEB
- www.oracle.com/security-alerts/cpuoct2021.htmlghsax_refsource_MISCWEB
- www.oracle.com/technetwork/security-advisory/cpujan2019-5072801.htmlghsax_refsource_CONFIRMWEB
- www.oracle.com/technetwork/security-advisory/cpujul2019-5072835.htmlghsax_refsource_MISCWEB
News mentions
0No linked articles in our index yet.