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
This commit is contained in:
Sam Brannen
2026-07-29 21:21:11 +03:00
parent 719311f09b
commit 9b42a40a2a
4 changed files with 90 additions and 5 deletions
@@ -253,6 +253,39 @@ properties. Alternatively, configure custom accessors via
`SimpleEvaluationContext.forPropertyAccessors(...)`, potentially disable assignment, and `SimpleEvaluationContext.forPropertyAccessors(...)`, potentially disable assignment, and
optionally activate method resolution and/or a type converter through the builder. 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]] [[expressions-type-conversion]]
=== Type Conversion === Type Conversion
@@ -38,6 +38,24 @@ import org.jspecify.annotations.Nullable;
* manually.</li> * manually.</li>
* </ul> * </ul>
* *
* <p><strong>WARNING</strong>: 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}
* &mdash; for example, by supplying a root object or by registering property
* accessors, resolvers, variables, or functions &mdash; 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 Andy Clement
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Sam Brannen * @author Sam Brannen
@@ -49,8 +49,8 @@ import org.springframework.expression.spel.SpelMessage;
* should be meaningfully restricted. Examples include but are not limited to * should be meaningfully restricted. Examples include but are not limited to
* data binding expressions, property-based filters, and others. To that effect, * data binding expressions, property-based filters, and others. To that effect,
* {@code SimpleEvaluationContext} is tailored to support only a subset of the * {@code SimpleEvaluationContext} is tailored to support only a subset of the
* SpEL language syntax, for example, excluding references to Java types, constructors, * SpEL language syntax &mdash; for example, excluding references to Java types,
* and bean references. * constructors, and bean references.
* *
* <p>When creating a {@code SimpleEvaluationContext} you need to choose the level of * <p>When creating a {@code SimpleEvaluationContext} you need to choose the level of
* support that you need for data binding in SpEL expressions: * 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, * read-only access to properties via {@link DataBindingPropertyAccessor}. Similarly,
* {@link SimpleEvaluationContext#forReadWriteDataBinding()} enables read and write access * {@link SimpleEvaluationContext#forReadWriteDataBinding()} enables read and write access
* to properties. Alternatively, configure custom accessors via * to properties. Alternatively, configure custom accessors via
* {@link SimpleEvaluationContext#forPropertyAccessors}, potentially * {@link SimpleEvaluationContext#forPropertyAccessors}, consider
* {@linkplain Builder#withAssignmentDisabled() disable assignment}, and optionally * {@linkplain Builder#withAssignmentDisabled() disabling assignment} (recommended),
* activate method resolution and/or a type converter through the builder. * and optionally activate method resolution and/or a type converter through the
* builder.
* *
* <p>Note that {@code SimpleEvaluationContext} is typically not configured * <p>Note that {@code SimpleEvaluationContext} is typically not configured
* with a default root object. Instead it is meant to be created once and * with a default root object. Instead it is meant to be created once and
@@ -87,6 +88,23 @@ import org.springframework.expression.spel.SpelMessage;
* <p>For more power and flexibility, in particular for internal configuration * <p>For more power and flexibility, in particular for internal configuration
* scenarios, consider using {@link StandardEvaluationContext} instead. * scenarios, consider using {@link StandardEvaluationContext} instead.
* *
* <p><strong>WARNING</strong>: {@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} &mdash; for example, by supplying a root
* object or by registering property accessors, method resolvers, variables, or
* functions &mdash; 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 Rossen Stoyanchev
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Sam Brannen * @author Sam Brannen
@@ -64,6 +64,22 @@ import org.springframework.util.Assert;
* consider using {@link SimpleEvaluationContext} instead which allows for * consider using {@link SimpleEvaluationContext} instead which allows for
* opting into several SpEL features as needed by specific use cases. * opting into several SpEL features as needed by specific use cases.
* *
* <p><strong>WARNING</strong>: {@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 &mdash; all
* backed by reflection &mdash; as well as the ability to reference beans in an
* {@code ApplicationContext} via a configured {@link BeanResolver}. For that
* reason, a {@code StandardEvaluationContext} must <strong>never</strong> 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 &mdash; for example, an
* expression supplied by an end user or received from an external system
* &mdash; 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 Andy Clement
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Sam Brannen * @author Sam Brannen