Sikau

Project: A secure API gateway · Day 3 · about 40 min

Sandboxed wasm plugins

Run untrusted formulas as WebAssembly: limits, caching, and catching traps.

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;

The rest of this lesson

  • Why not evalexplain
  • Limits and cachingexplain
  • Sandbox propertiesmatch
  • Risk to mitigationmatch
  • Run plugins safelywrite code
  • Badge quizquiz
  • What you builtrecap

Continue this lesson free — run real code in your browser

Continue with Google

See all 4 lessons of Project: A secure API gateway