liveBook · Manning

Dynamic evaluation

As explained in Grokking Web Application Security

Dynamic evaluation is the execution of code represented as a value in memory rather than stored in a source file.

Dynamic evaluation runs code held in memory rather than code loaded from a source file. In JavaScript, eval() turns a string into executable code. That capability becomes dangerous when the string originates with an HTTP request: an attacker may turn application input into instructions for the web server. section 12.1

const express = require('express')
const app     = express()

app.use(express.json())

app.post('/execute-command', (req, res) => {
 const result = eval(command)
 res.json({ result })
})

This endpoint illustrates the red flag: evaluating a command received by a web application gives an attacker a path to arbitrary code execution in the server runtime. section 12.1

The resulting attack is remote code execution (RCE). Malicious code running in the server runtime can explore filesystem contents or contribute to a full system takeover. Obvious eval() calls should raise concerns in review, but real RCE flaws often arise through subtler paths where input eventually reaches a dynamic execution feature. section 12.1

Treat dynamic evaluation as a security boundary:

  • Never execute untrusted HTTP-request input as code. section 12.1
  • Review code paths that transform strings or user-controlled expressions into executable server-side instructions. section 12.1
  • Avoid using the host language's dynamic evaluator as the easy implementation for a web-facing expression language. section 12.2

A common temptation appears when an application offers a domain-specific language (DSL), such as search operators or spreadsheet-style formulas. DSLs commonly accept single-line expressions, and dynamically evaluating those expressions in the server language is easy—but generally the wrong design. Without a strong grasp of sandboxing, it can allow RCE vulnerabilities to creep in. section 12.2

Evaluate a DSL without exposing the host runtime

One option is an embedded scripting language such as Lua. The application can explicitly control which host-language objects, if any, are passed to the Lua runtime during evaluation. Another option is to formally define the DSL syntax, tokenize expressions through lexical analysis, then parse and evaluate only the operations the DSL permits. section 12.2 section 12.2

import lupa

lua        = lupa.LuaRuntime(
               unpack_returned_tuples=True) #1
expression = "2 + 3"                        #2
result     = lua.execute(expression)        #3

The Lua example evaluates a simple expression in an embedded runtime, illustrating a separate evaluation environment for application-defined expressions. section 12.2

The practical rule is simple: code-like input is not harmless merely because it is stored in a string. Keep untrusted input out of dynamic evaluators, and design expression features around restricted runtimes or explicitly parsed syntax instead of unrestricted host-language execution. section 12.1 section 12.2

How Grokking Web Application Security covers it

How deep it goes
Defines in-memory code execution and contrasts unsafe DSL evaluation with embedded runtimes and lexical-analysis parsing.
Examples
Uses an Express eval endpoint and Python examples embedding Lua to evaluate arithmetic expressions.
What it assumes
Introduces dynamic evaluation from zero while assuming familiarity with web requests, server runtimes, and code expressions.
What you can do after
Evaluate/understand why untrusted request input must not reach dynamic evaluators and identify safer DSL implementation directions.
How it connects
Connects dynamic evaluation to remote code execution, domain-specific languages, sandboxing, Lua, and lexical analysis.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Grokking Web Application Security. The section links point to the parts of the book it draws on.