The approved globals — the only host globals an expression can reach.
This is the single list reviewers should check. Every other free identifier in an expression must
be an evaluation-context key or an arrow-function parameter in scope; anything else is refused
before compilation (see SafeExpressionEvaluator.ScreenExpression).
An approved global is usable ONLY in call position — Math.max(a, b), Number(x) — never as a
bare value, a property read (Math.PI), or a callback (items.map(Number)). That rule is what
stops a function being handed to code that calls it with attacker-chosen arguments: two confirmed
bypasses of the earlier denylist did exactly that (a.reduce(fetch) and
p.reduce(Object.assign)).
Every listed member is a pure function of its arguments. Deliberately absent: Object.assign,
Object.defineProperty, Object.getPrototypeOf/setPrototypeOf (mutate or open the prototype
chain), Math.random (a guard that changes per run is not a guard), String.fromCharCode, and
every host API (fetch, setTimeout, require, process, ...).
Both halves of Math.abs(x) are fixed identifiers in the AST, so admitting them adds no dynamic
lookup.
The approved globals — the only host globals an expression can reach.
This is the single list reviewers should check. Every other free identifier in an expression must be an evaluation-context key or an arrow-function parameter in scope; anything else is refused before compilation (see SafeExpressionEvaluator.ScreenExpression).
An approved global is usable ONLY in call position —
Math.max(a, b),Number(x)— never as a bare value, a property read (Math.PI), or a callback (items.map(Number)). That rule is what stops a function being handed to code that calls it with attacker-chosen arguments: two confirmed bypasses of the earlier denylist did exactly that (a.reduce(fetch)andp.reduce(Object.assign)).Every listed member is a pure function of its arguments. Deliberately absent:
Object.assign,Object.defineProperty,Object.getPrototypeOf/setPrototypeOf(mutate or open the prototype chain),Math.random(a guard that changes per run is not a guard),String.fromCharCode, and every host API (fetch,setTimeout,require,process, ...).Both halves of
Math.abs(x)are fixed identifiers in the AST, so admitting them adds no dynamic lookup.