Security Model

nuforge is designed to safely evaluate page expressions authored in its DSL. The protections are defense-in-depth at the data layer: rather than relying on a single gate, several independent guards stack so that an expression must pass through all of them before it can run.

AST allow-list

The parser only accepts a safe subset of expression nodes: literals, identifiers, member access, arrays, objects, binary/logical/unary operators, conditional expressions, function calls, arrow functions, and template literals. Anything outside that subset is rejected at parse time, before evaluation ever begins.

Specifically, the parser rejects the new operator, function expressions, this, typeof, delete, strict-equality operators (write ==/!= instead), the ++/-- operators, comma sequences, tagged templates, and arbitrary statements. Because these are caught while parsing, an invalid expression never reaches the runtime.

Property-access guard

Access to constructor, __proto__, and prototype is blocked on both member access and object keys. The block applies at parse time AND during evaluation, which closes prototype-chain escapes that would otherwise let an expression climb out of the data layer.

Here is a small contrast between expressions that are accepted and ones that are rejected:

{user.name}            // ok
{items.length > 0}     // ok
{new Date()}           // rejected: `new` is not allowed
{obj.constructor}      // rejected: property guard

Recursion / DoS guard

Evaluation enforces a maximum recursion depth. A malicious or runaway expression therefore cannot exhaust the call stack, so a single bad expression cannot take down the runtime.

Frozen host state

External state is deep-frozen before it is handed to the DSL. As a result, DSL expressions can only read host state and never mutate it. See the externals page for how host state is provided.

Rendering safety

  • <script> is rejected by the parser and is never raw-rendered, so DSL content can't execute arbitrary JavaScript.
  • dangerouslySetInnerHTML is stripped by the React renderer and by code export, so a page can't inject raw HTML.
  • URL attributes are sanitized in static export (toHtml): javascript: / vbscript: / data:text/html URLs are dropped. (React's renderer already neutralizes javascript: URLs at runtime.)

Collaboration & writes

Inbound collaborative AST is schema-validated before being merged, so a malformed or hostile document cannot slip past the parser guards by arriving over the wire. Internal writes use a guarded assignment that prevents prototype pollution.

Not a full sandbox

This is defense-in-depth at the data layer, NOT a full VM sandbox. For fully untrusted third-party content, add an extra boundary, such as a QuickJS or iframe sandbox, at your extension points.

Next steps

  • DSL — the expression language these guards protect
  • Externals — how host state is provided and frozen