Skip to content

[Medium][ssr] DOM-backed evaluateSSR uses new Function() eval fallback (defeats CSP-safe design) + missing proto guard #167

Description

@JosunLP

Severity: 🟡 Medium (High if templates can carry untrusted content, e.g. a CMS/page-builder)

Location

src/ssr/render.ts:189-197 (new Function() fallback) and :174-187 (dot-path, missing proto guard). Used by the DOM-backed renderer — active whenever a global/configured DOMParser exists (browsers, happy-dom, or configureSSR({ backend: 'dom' })).

Description

evaluateSSR falls back to dynamic code generation for any non-trivial expression:

const fn = new Function(...keys, `return (${trimmed});`);
return fn(...values);

This directly contradicts the module's stated security posture — src/ssr/expression.ts was written specifically to be CSP-safe (no eval/Function) — and re-introduces unsafe-eval on the DOM path. If any part of a template expression is attacker-influenced, this is code execution.

Additionally, the fast dot-notation path (render.ts:174-187) does not call isPrototypePollutionKey, unlike the hardened expression.ts (lookupIdent/safeMember). evaluateSSR('constructor.constructor', ctx) walks the prototype chain and returns the Function constructor — an inconsistent hardening gap and a stepping stone when combined with the new Function fallback.

Suggested fix

Replace evaluateSSR with the CSP-safe evaluateExpression from expression.ts (already used by the pure renderer), eliminating both the new Function fallback and the prototype-pollution gap, and unifying evaluator behaviour across backends.


Filed as part of a full-codebase security & correctness audit.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingmedium-priorityMedium severitysecurityChanges to the security modulessrChanges to the ssr module

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions