Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/no-eval-in-revive.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@workflow/core": patch
---

Replace `eval` in `serialization.ts` `revive()` helper with `JSON.parse`. `devalue.stringify()` output is always valid JSON (special values are encoded as negative integer sentinels), so `JSON.parse` is a safe drop-in that eliminates the `eval` anti-pattern.
8 changes: 5 additions & 3 deletions packages/core/src/serialization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -675,9 +675,11 @@ type Revivers = {
};

function revive(str: string) {
// biome-ignore lint/security/noGlobalEval: Eval is safe here - we are only passing value from `devalue.stringify()`
// biome-ignore lint/complexity/noCommaOperator: This is how you do global scope eval
return (0, eval)(`(${str})`);
// devalue.stringify() always produces valid JSON: special values
// (undefined, NaN, Infinity, -0) are encoded as negative integer
// sentinels and the remaining structure is ordinary JSON. Parsing
// with JSON.parse yields the flattened form that unflatten() expects.
Comment on lines +679 to +681
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The explanatory comment lists special values encoded by devalue.stringify(), but it omits -Infinity (and devalue encodes that as a sentinel too). Consider updating the comment to include -Infinity or to phrase it more generally (e.g., “special values like undefined/NaN/±Infinity/-0”).

Suggested change
// (undefined, NaN, Infinity, -0) are encoded as negative integer
// sentinels and the remaining structure is ordinary JSON. Parsing
// with JSON.parse yields the flattened form that unflatten() expects.
// like undefined, NaN, Infinity, -Infinity, and -0 are encoded as
// negative integer sentinels and the remaining structure is ordinary
// JSON. Parsing with JSON.parse yields the flattened form that
// unflatten() expects.

Copilot uses AI. Check for mistakes.
return JSON.parse(str);
}

function getCommonReducers(global: Record<string, any> = globalThis) {
Expand Down
Loading