From 9b42a40a2ac732fb251626d685823b27f05579e7 Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Sun, 26 Jul 2026 11:26:17 +0300 Subject: [PATCH] Document security implications of evaluating untrusted SpEL expressions This commit clarifies in the Javadoc for EvaluationContext, StandardEvaluationContext, and SimpleEvaluationContext (as well as in the SpEL reference documentation) that StandardEvaluationContext must never be used to evaluate expressions from an untrusted source, and that SimpleEvaluationContext's restricted language and feature subset is only a best-effort measure. The updated documentation also defines a "trusted" source as a developer or administrator of the application and points out that it is the responsibility of the code that configures an EvaluationContext to ensure that no object reachable via the context exposes dangerous operations. Closes gh-36997 --- .../pages/core/expressions/evaluation.adoc | 33 +++++++++++++++++++ .../expression/EvaluationContext.java | 18 ++++++++++ .../spel/support/SimpleEvaluationContext.java | 28 +++++++++++++--- .../support/StandardEvaluationContext.java | 16 +++++++++ 4 files changed, 90 insertions(+), 5 deletions(-) diff --git a/framework-docs/modules/ROOT/pages/core/expressions/evaluation.adoc b/framework-docs/modules/ROOT/pages/core/expressions/evaluation.adoc index 6f18e635436..e7bee3b66b6 100644 --- a/framework-docs/modules/ROOT/pages/core/expressions/evaluation.adoc +++ b/framework-docs/modules/ROOT/pages/core/expressions/evaluation.adoc @@ -253,6 +253,39 @@ properties. Alternatively, configure custom accessors via `SimpleEvaluationContext.forPropertyAccessors(...)`, potentially disable assignment, and optionally activate method resolution and/or a type converter through the builder. +[[expressions-evaluation-context-security]] +=== Security Considerations + +SpEL is a powerful expression language that can invoke constructors and methods, read and +write properties and fields, and reference beans – all backed by reflection. Because of +this power, evaluating a SpEL expression obtained from an untrusted source is inherently +dangerous and should generally be avoided, since doing so can effectively grant that +source the ability to execute arbitrary code within the application, regardless of which +`EvaluationContext` implementation is used. + +Throughout this section, a source is considered "trusted" only if it is a developer of +the application or an administrator responsible for configuring or operating the +application. Any other source of a SpEL expression must be treated as untrusted – for +example, an expression supplied by an end user of the application or received from an +external system. + +[WARNING] +==== +`StandardEvaluationContext` exposes the complete SpEL language and must *never* be used +to evaluate an expression obtained from an untrusted source. +==== + +Although `SimpleEvaluationContext` restricts the SpEL language to a subset of its +features, that restriction is provided on a best-effort basis and does not guarantee that +expression evaluation is safe. Since an expression can potentially invoke any property, +method, or function reachable via the configured root object, property accessors, method +resolvers, variables, and functions, care must be taken if you choose to evaluate +expressions from an untrusted source. It is therefore the responsibility of the code that +configures an `EvaluationContext` – for example, by supplying a root object or by +registering property accessors, resolvers, variables, or functions – to ensure that none +of the objects reachable via the context expose operations that would be dangerous if +invoked by an expression from an untrusted source. + [[expressions-type-conversion]] === Type Conversion diff --git a/spring-expression/src/main/java/org/springframework/expression/EvaluationContext.java b/spring-expression/src/main/java/org/springframework/expression/EvaluationContext.java index c9b55f29a8c..3e807bdac53 100644 --- a/spring-expression/src/main/java/org/springframework/expression/EvaluationContext.java +++ b/spring-expression/src/main/java/org/springframework/expression/EvaluationContext.java @@ -38,6 +38,24 @@ import org.jspecify.annotations.Nullable; * manually. * * + *
WARNING: Evaluating a SpEL expression obtained from an + * untrusted source is inherently dangerous, since doing so can effectively + * grant that source the ability to execute arbitrary code within the + * application. See the class-level documentation for + * {@code StandardEvaluationContext} and {@code SimpleEvaluationContext} for + * details on the trust model applicable to each implementation. Regardless of + * which {@code EvaluationContext} implementation is in use, any restrictions + * that an implementation imposes on the SpEL language are provided on a + * best-effort basis and do not, by themselves, guarantee that expression + * evaluation is safe. An expression can potentially invoke any property, method, + * or function reachable via the configured root object, property accessors, + * index accessors, resolvers, variables, and functions. It is therefore the + * responsibility of the code that configures an {@code EvaluationContext} + * — for example, by supplying a root object or by registering property + * accessors, resolvers, variables, or functions — to ensure that none of + * those reachable objects expose operations that would be dangerous if invoked + * by an expression from an untrusted source. + * * @author Andy Clement * @author Juergen Hoeller * @author Sam Brannen diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/support/SimpleEvaluationContext.java b/spring-expression/src/main/java/org/springframework/expression/spel/support/SimpleEvaluationContext.java index e18599bab91..1e6931daa4c 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/support/SimpleEvaluationContext.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/support/SimpleEvaluationContext.java @@ -49,8 +49,8 @@ import org.springframework.expression.spel.SpelMessage; * should be meaningfully restricted. Examples include but are not limited to * data binding expressions, property-based filters, and others. To that effect, * {@code SimpleEvaluationContext} is tailored to support only a subset of the - * SpEL language syntax, for example, excluding references to Java types, constructors, - * and bean references. + * SpEL language syntax — for example, excluding references to Java types, + * constructors, and bean references. * *
When creating a {@code SimpleEvaluationContext} you need to choose the level of * support that you need for data binding in SpEL expressions: @@ -65,9 +65,10 @@ import org.springframework.expression.spel.SpelMessage; * read-only access to properties via {@link DataBindingPropertyAccessor}. Similarly, * {@link SimpleEvaluationContext#forReadWriteDataBinding()} enables read and write access * to properties. Alternatively, configure custom accessors via - * {@link SimpleEvaluationContext#forPropertyAccessors}, potentially - * {@linkplain Builder#withAssignmentDisabled() disable assignment}, and optionally - * activate method resolution and/or a type converter through the builder. + * {@link SimpleEvaluationContext#forPropertyAccessors}, consider + * {@linkplain Builder#withAssignmentDisabled() disabling assignment} (recommended), + * and optionally activate method resolution and/or a type converter through the + * builder. * *
Note that {@code SimpleEvaluationContext} is typically not configured * with a default root object. Instead it is meant to be created once and @@ -87,6 +88,23 @@ import org.springframework.expression.spel.SpelMessage; *
For more power and flexibility, in particular for internal configuration * scenarios, consider using {@link StandardEvaluationContext} instead. * + *
WARNING: {@code SimpleEvaluationContext} takes a + * best-effort approach to restricting the SpEL language to a subset of its + * features; however, it cannot guarantee that evaluation of an expression is + * safe. Evaluating a SpEL expression obtained from an untrusted source is inherently + * dangerous and should generally be avoided, since doing so can effectively grant + * that source the ability to execute arbitrary code within the application. Even + * within the restricted language subset supported by {@code SimpleEvaluationContext}, + * an expression can potentially invoke any property, method, or function reachable + * via the configured root object, property accessors, method resolvers, variables, + * and functions. It is therefore the responsibility of the code that configures a + * {@code SimpleEvaluationContext} — for example, by supplying a root + * object or by registering property accessors, method resolvers, variables, or + * functions — to ensure that none of those reachable objects expose + * operations that would be dangerous if invoked by an expression from an + * untrusted source. For details on what qualifies as a "trusted" source, see + * {@link StandardEvaluationContext}. + * * @author Rossen Stoyanchev * @author Juergen Hoeller * @author Sam Brannen diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/support/StandardEvaluationContext.java b/spring-expression/src/main/java/org/springframework/expression/spel/support/StandardEvaluationContext.java index 721d4380462..01155813b3e 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/support/StandardEvaluationContext.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/support/StandardEvaluationContext.java @@ -64,6 +64,22 @@ import org.springframework.util.Assert; * consider using {@link SimpleEvaluationContext} instead which allows for * opting into several SpEL features as needed by specific use cases. * + *
WARNING: {@code StandardEvaluationContext} exposes the + * complete SpEL language, including the ability to invoke arbitrary constructors + * and methods and to read and write arbitrary properties and fields — all + * backed by reflection — as well as the ability to reference beans in an + * {@code ApplicationContext} via a configured {@link BeanResolver}. For that + * reason, a {@code StandardEvaluationContext} must never be used + * to evaluate a SpEL expression obtained from an untrusted source. In this context, + * a "trusted" source is limited to a developer of the application or an + * administrator who is responsible for configuring or operating the + * application. Any other source of a SpEL expression — for example, an + * expression supplied by an end user or received from an external system + * — must be treated as untrusted. Note, however, that evaluating a SpEL + * expression obtained from an untrusted source is inherently dangerous + * regardless of the {@code EvaluationContext} implementation in use; see + * {@link SimpleEvaluationContext} for further details. + * * @author Andy Clement * @author Juergen Hoeller * @author Sam Brannen