Running other people's code safely
Our clients send formulas. Evaluating them with eval would hand attackers your server. Compiling them to WebAssembly instead puts them in a sandbox: they can only do arithmetic on the numbers we pass in. Still, be strict: limit the size, validate inputs, cache compiled modules, and turn traps into clean errors.
The sandbox
const cache = new Map();
const isI32 = (n) => Number.isInteger(n) && n >= -2147483648 && n <= 2147483647;
function runPlugin(source, x, y) {
if (typeof source !== "string" || source.length > 200) return { ok: false, error: "Formula too long" };
if (!isI32(x) || !isI32(y)) return { ok: false, error: "Bad input" };
let f = cache.get(source);
if (!f) {
try {
f = compileExpr(source); // compile once, reuse
} catch (e) {
return { ok: false, error: e.message };
}
cache.set(source, f);
}
try {
return { ok: true, value: f(x, y) };
} catch (e) {
return { ok: false, error: e instanceof WebAssembly.RuntimeError ? "Runtime error" : e.message };
}
}
const cacheSize = () => cache.size;