Java web frameworks lean on expression languages to move data between the request, the controller, and the view. A page tag resolves a property path, a controller maps a request parameter onto an object graph, an annotation names a rule to evaluate. Each of those is an expression engine, and when the string it evaluates comes from request data the grammar becomes an execution surface inside the application process.
Two families appear here. The unified EL defined by the servlet stack and shared by JSP and JSF (${...} in JSP, #{...} in JSF) was built to read and write scoped attributes, and from EL 2.2 onward it invokes methods, which reaches reflection and the host runtime. The framework engines (SpEL in Spring, OGNL in Struts2 and older WebWork, MVEL in several binding and rule layers) are full object languages: they name arbitrary classes, construct objects, and call methods, so the baseline reachable surface already includes java.lang.Runtime and ProcessBuilder.
The route from an injected expression to impact is engine-specific, so the subtrees are split by engine:
- MVEL: a Java-like expression language with direct access to Java types, evaluated through
MVEL.evalor a compiled expression. - JSF EL: the
#{...}unified EL of JavaServer Faces, reaching scoped objects for authorization bypass and reflection for code execution. - JSP EL: the
${...}unified EL of JavaServer Pages, covering authorization bypass and code execution. - OGNL: the Object-Graph Navigation Language of Struts2, covering a directory listing evaluation probe, remote code execution, and remote file inclusion.
- SpEL: the Spring Expression Language, covering code execution and WAF bypass.