3.0 KiB
CodeTransformer
(no submodules)
Purpose
CodeTransformer is a defence-in-depth layer that pattern-matches dangerous code constructs before they reach the engine. The eleven built-in rules catch the obvious foot-guns — process.exit, require, dynamic import, eval, the Function constructor, globalThis, prototype-chain probes, and the constructor['constructor'] escape — plus two warning-only rules for infinite loops and a maxCodeLength guard that caps script size at 100KB by default.
The transformer is regex-based by design. A full AST parser would catch contrived bypasses (commented-out code that gets reassembled at runtime, string concatenation that builds a denylisted identifier) but at the cost of pulling in a megabyte of parser. The engine-level boundary (vm-engine, worker-engine, spawn-engine) is the actual security layer; the transformer raises the floor on accidental harm and surfaces clearly-named blocks for malicious harm.
Features
- Ten built-in security rules covering the documented OWASP-recommended dangerous-pattern catalogue for in-process script execution.
- One
max-code-lengthguard for script size. enableBuiltinRules: falseopt-out for callers shipping their own rules.customRulesslot for additive caller rules.transform(code)returns{ code, blocked, blockedBy?, applied, warnings }.wouldBlock(code)returns{ blocked, reason? }for cheap pre-flight checks.- Every block fires an OTel counter via
recordRuleBlock(rule).
Usage: Basic
import { CodeTransformer } from "@suaveplan/sandbox/code-transformer";
const t = new CodeTransformer();
const r = t.transform("1 + 1");
console.log(r.blocked, r.applied);
Usage: Advanced
Extend the transformer with a custom auditing rule that rewrites a vendor SDK call into a logged wrapper before execution:
import { CodeTransformer } from "@suaveplan/sandbox/code-transformer";
const t = new CodeTransformer({
customRules: [
{
name: "audit-vendor-call",
pattern: /\bvendor\.send\(/g,
replacement: "vendor.__audited_send(",
blocking: false,
},
],
});
API Reference
BUILTIN_RULES: readonly TransformRule[].new CodeTransformer(config?: CodeTransformerConfig).transform(code: string): TransformResult.wouldBlock(code: string): { blocked: boolean; reason?: string }.getRules(): readonly TransformRule[].
Implementation Notes
The rule list is iterated in declaration order; the first matching blocking
rule wins. Replacement rules apply globally (the g flag is forced on every
regex) so multiple occurrences are rewritten in one pass. Warning-only rules
that aren't replacements only append a warning string — they never mutate the
code. Pattern strings (vs. literal regex) get the g flag added in
ruleRegex so caller-supplied string patterns behave consistently with
caller-supplied regex patterns.