Interface ELSandbox

All Known Implementing Classes:
ELSandbox.StandardELSandbox

public interface ELSandbox
What an expression parsed at runtime may reach through reflection.

An expression declared with io.micronaut.el.annotation.ELExpression is written by the developer and compiled, so it is as trusted as the rest of the source. An expression string built at runtime is not: the specification resolves properties, methods, static members and constructors dynamically, and where that resolution reflects, an expression that reaches java.lang.Runtime, a java.lang.Class or the reflection API can run whatever the process can. A sandbox closes those paths while leaving the language intact.

The sandbox is consulted where the resolution of such an expression reflects, and nowhere else: a method, a constructor, a static member or a function an executor resolves reflectively, and a property a resolver reads that is not known to read it without reflection - the resolvers of the specification that read a bean (an Optional holding one included), a record, a class or a static import, and any resolver the module does not know. It is asked about the base object before the access and about the value the access produced after it, so reflection neither works on nor hands the expression a type it denies. What the application described while it compiled - its bean introspections, the executable methods of its beans, the methods it registered - and the maps, lists and arrays an expression indexes are reached without it: they lead only where the application already chose to lead. An expression compiled at compilation time never consults it.

standard() is applied to every expression the micronaut-jakarta-el-interpreter module creates. Register another one, UNRESTRICTED included, on the context the expression is evaluated with:

context.putContext(ELSandbox.class, ELSandbox.UNRESTRICTED);

A sandbox is not a security boundary on its own: it bounds what reflection reaches, not what the beans an expression reaches then do. Treat an expression string from an untrusted source as untrusted input.

Since:
1.1
Author:
Denis Stepanov
See Also:
  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Interface
    Description
    static final class 
    The default deny list.
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    static final ELSandbox
    The sandbox allowing everything, which is how an expression compiled at compilation time is evaluated.
  • Method Summary

    Modifier and Type
    Method
    Description
    boolean
    allowsType(Class<?> type)
    Whether reflection may reach the members of a type, which is asked of the base object of every reflective access and of the value every reflective access produces.
    static ELSandbox
    of(@Nullable jakarta.el.ELContext context)
    Reads the sandbox an expression is evaluated under from the context, which is standard() unless one was registered with ELContext.putContext(ELSandbox.class, sandbox).
    static ELSandbox
    The sandbox applied to the expressions parsed at runtime: it denies the types through which an expression escapes into arbitrary Java, and lets everything else through.
  • Field Details

    • UNRESTRICTED

      static final ELSandbox UNRESTRICTED
      The sandbox allowing everything, which is how an expression compiled at compilation time is evaluated.
  • Method Details

    • standard

      static ELSandbox standard()
      The sandbox applied to the expressions parsed at runtime: it denies the types through which an expression escapes into arbitrary Java, and lets everything else through.
      Returns:
      The standard sandbox
    • of

      static ELSandbox of(@Nullable jakarta.el.ELContext context)
      Reads the sandbox an expression is evaluated under from the context, which is standard() unless one was registered with ELContext.putContext(ELSandbox.class, sandbox).
      Parameters:
      context - The context, can be null
      Returns:
      The sandbox
    • allowsType

      boolean allowsType(Class<?> type)
      Whether reflection may reach the members of a type, which is asked of the base object of every reflective access and of the value every reflective access produces.

      No member is denied by its name: every member that leads from an allowed object to a denied one, such as getClass or getClassLoader, produces a value of a denied type, and is stopped by that.

      Parameters:
      type - The type the expression reached
      Returns:
      Whether the expression may use it