3.7 KiB
eval-safe
(no submodules)
Purpose
Provides serializeEvalSafe and deserializeEvalSafe as an explicit opt-in adapter for scenarios where the standard tagged JSON or MessagePack codecs cannot be used — for example, when the payload must include JavaScript Function values, RegExp literals with complex syntax, or other types that cannot be expressed in a JSON-safe intermediate. The adapter wraps the serialize-javascript library, which is purpose-built for this use case (e.g. server-side Redux initial state injection into HTML).
This module lives under the ./unsafe subpath export and must never appear in the main @suaveplan/serialize bundle. Importing it is an explicit acknowledgment of the security trade-off.
Features
serializeEvalSafe— produces a JavaScript expression string viaserialize-javascriptthat, when eval'd, reconstructs the original value including Functions and RegExpsdeserializeEvalSafe— evaluates the produced string via(0, eval)(...)(indirect eval) to reconstruct the value- Security warning emitted on every call unless
{ ignoreSecurityWarning: true }is passed EvalSafeOptionsinterface for suppressing warnings in controlled environments
Usage: Basic Example
import { serializeEvalSafe, deserializeEvalSafe } from "@suaveplan/serialize/unsafe";
// Suppress warnings in a trusted server-side context
const str = serializeEvalSafe({ fn: () => 42 }, { ignoreSecurityWarning: true });
const restored = deserializeEvalSafe(str, { ignoreSecurityWarning: true });
// (restored as any).fn() === 42
Usage: Advanced Example
import { serializeEvalSafe } from "@suaveplan/serialize/unsafe";
// Inject Redux initial state into an HTML page server-side.
// This is the canonical use case for serialize-javascript.
const html = `
<script>
window.__INITIAL_STATE__ = ${serializeEvalSafe(reduxState, { ignoreSecurityWarning: true })};
</script>
`;
API Reference
serializeEvalSafe(value: unknown, opts?: EvalSafeOptions): string
Serialize value using serialize-javascript. The output is a JavaScript expression string, not JSON.
Parameters:
value— any JavaScript value, including Functions and RegExpsopts.ignoreSecurityWarning— passtrueto suppress theconsole.warn
Returns: a JavaScript expression string.
deserializeEvalSafe(json: string, opts?: EvalSafeOptions): unknown
Evaluate json as a JavaScript expression and return the result.
Parameters:
json— a string produced byserializeEvalSafe; MUST be from a trusted sourceopts.ignoreSecurityWarning— passtrueto suppress theconsole.warn
Returns: the reconstructed value.
Security: Uses indirect eval ((0, eval)(...)), which runs in the global scope rather than the local closure scope, slightly reducing the attack surface compared to direct eval.
EvalSafeOptions
interface EvalSafeOptions {
ignoreSecurityWarning?: boolean;
}
Implementation Notes
- The
(0, eval)(...)pattern (indirect eval) is used intentionally: it evaluates in the global scope rather than capturing local variables, which slightly reduces the blast radius if a malicious string is accidentally evaluated. serialize-javascriptis listed as a regular dependency (not a dev dependency) because it is shipped as part of the/unsafesubpath. The main bundle's Rollup config marks it asexternal, so it is never bundled intodist/index.js.- The biome
lint/security/noEvalrule is suppressed with a comment at the call site to document that the eval usage is intentional, reviewed, and isolated to this specific adapter.